SPOJ GSS(Can you answer the Queries)系列 7/8

GSS1

线段树最大子段和裸题,不带修改,注意pushup。

然而并不会猫树之类的东西

 #include<bits/stdc++.h>
 #define MAXN 50001
 using namespace std;
 struct node{
     int l , r , sum , lMax , rMax , midMax;
 }Tree[MAXN << ];
 int a[MAXN] , rMax , allMax , N;

 inline int max(int a , int b){
     return a > b ? a : b;
 }

 void init(int dir , int l , int r){
     Tree[dir].l = l;
     Tree[dir].r = r;
     if(l == r)
         Tree[dir].lMax = Tree[dir].rMax = Tree[dir].midMax = Tree[dir].sum = a[l];
     else{
         init(dir <<  , l , (l + r) >> );
         init(dir <<  |  , ((l + r) >> ) +  , r);
         Tree[dir].sum = Tree[dir << ].sum + Tree[dir <<  | ].sum;
            Tree[dir].lMax = max(Tree[dir << ].lMax , Tree[dir << ].sum + Tree[dir <<  | ].lMax);
         Tree[dir].rMax = max(Tree[dir <<  | ].rMax , Tree[dir <<  | ].sum + Tree[dir << ].rMax);
         Tree[dir].midMax = max(max(Tree[dir << ].midMax , Tree[dir <<  | ].midMax) , Tree[dir << ].rMax + Tree[dir <<  | ].lMax);
     }
 }

 void findMax(int dir , int l , int r){
     if(Tree[dir].l >= l && Tree[dir].r <= r){
         allMax = max(allMax , max(rMax + Tree[dir].lMax , Tree[dir].midMax));
         rMax = max(max(Tree[dir].rMax , Tree[dir].sum + rMax) , );
         return;
     }
     )
         findMax(dir <<  , l , r);
     )
         findMax(dir <<  |  , l , r);
 }

 inline void work(int x , int y){
     allMax = -0x7fffffff;
     rMax = ;
     findMax( , x , y);
     printf("%d\n" , allMax);
 }

 int main(){
     scanf("%d" , &N);
      ; i <= N ; i++)
         scanf("%d" , a + i);
     init( ,  , N);
     int T;
     for(scanf("%d" , &T) ; T ; T--){
         int a , b;
         scanf("%d%d" , &a , &b);
         work(a , b);
     }
     ;
 }

GSS1

GSS2

因为不是传统的最大子段和所以单独开了一页:Sol

GSS3

带修改的GSS1

其实也没什么区别只是莫名代码长了很多

 #include<bits/stdc++.h>
 #define MAXN 50001
 #define ll long long
 using namespace std;
 inline ll read(){
     ll a = ;
     char c = getchar();
     ;
     while(!isdigit(c)){
         ;
         c = getchar();
     }
     ) + (a << ) + (c ^ ') , c = getchar();
     return f ? -a : a;
 }

 inline void print(ll x){
     ] , dirN = ;
     ){
         putchar('-');
         x = -x;
     }
     while(x){
         num[dirN++] = x % ;
         x /= ;
     }
     )    putchar(');
     );
     putchar('\n');
 }

 struct node{
     ll l , r , lMax , rMax , sum , midMax;
 }Tree[MAXN << ];
 ll num[MAXN] , N , nowMaxLeft , nowMax;

 inline ll max(ll a , ll b){return a > b ? a : b;}

 void build(ll dir , ll l , ll r){
     Tree[dir].l = l;    Tree[dir].r = r;
     if(l == r)
         Tree[dir].lMax = Tree[dir].rMax = Tree[dir].midMax = Tree[dir].sum = num[l];
     else{
         build(dir <<  , l , l + r >> );
         build(dir <<  |  , (l + r >> ) +  , r);
         Tree[dir].lMax = max(Tree[dir << ].sum + Tree[dir <<  | ].lMax , Tree[dir << ].lMax);
         Tree[dir].rMax = max(Tree[dir <<  | ].sum + Tree[dir << ].rMax , Tree[dir <<  | ].rMax);
         Tree[dir].sum = Tree[dir << ].sum + Tree[dir <<  | ].sum;
         Tree[dir].midMax = max(Tree[dir <<  | ].lMax + Tree[dir << ].rMax , max(Tree[dir << ].midMax , Tree[dir <<  | ].midMax));
     }
 }

 void change(ll dir , ll a , ll b){
     if(Tree[dir].l == a && Tree[dir].r == a){
         Tree[dir].lMax = Tree[dir].rMax = Tree[dir].midMax = Tree[dir].sum = b;
         return;
     }
     )    change(dir <<  |  , a , b);
      , a , b);
     Tree[dir].lMax = max(Tree[dir << ].sum + Tree[dir <<  | ].lMax , Tree[dir << ].lMax);
     Tree[dir].rMax = max(Tree[dir <<  | ].sum + Tree[dir << ].rMax , Tree[dir <<  | ].rMax);
     Tree[dir].sum = Tree[dir << ].sum + Tree[dir <<  | ].sum;
     Tree[dir].midMax = max(Tree[dir <<  | ].lMax + Tree[dir << ].rMax , max(Tree[dir << ].midMax , Tree[dir <<  | ].midMax));
 }

 void findMax(ll dir , ll a , ll b){
     if(Tree[dir].l >= a && Tree[dir].r <= b){
         nowMax = max(nowMax , max(max(nowMaxLeft , ) + Tree[dir].lMax , Tree[dir].midMax));
         nowMaxLeft = max(nowMaxLeft + Tree[dir].sum , Tree[dir].rMax);
         return;
     }
     )    findMax(dir <<  , a , b);
     )    findMax(dir <<  |  , a , b);
 }

 int main(){
     N = read();
      ; i <= N ; i++)    num[i] = read();
     build( ,  , N);
     register int a , b , M = read();
     while(M--)
         ){
             a = read();    b = read();
             nowMaxLeft = nowMax = -0x7f7f7f7f;
             findMax( , a , b);
             print(max(nowMax , nowMaxLeft));
         }
         else{
             a = read();    b = read();
             change( , a , b);
         }
     ;
 }

GSS3

GSS4

话说这东西似乎叫做势能线段树?

$10^{18}$开$6-7$次根就会变成$1$,而$\sqrt{1} = 1$,所以我们可以建一棵这样子的线段树:最开始几次修改暴力到叶子节点进行修改,在之后的某一次修改中,如果某一个节点所表示的区间中所有数就变成了$1$,就不往下走

 #include<bits/stdc++.h>
 #define MAXN 100010
 #define int unsigned long long
 using namespace std;

 inline int read(){
     ;
     char c = getchar();
     while(c != EOF && !isdigit(c))
         c = getchar();
     while(c != EOF && isdigit(c)){
         a = (a << ) + (a << ) + (c ^ ');
         c = getchar();
     }
     return a;
 }

 struct node{
     int sum;
     bool f;
 }Tree[MAXN << ];

 inline void pushup(int now){
     Tree[now].sum = Tree[now << ].sum + Tree[now <<  | ].sum;
     Tree[now].f = Tree[now << ].f && Tree[now <<  | ].f;
 }

 void init(int now , int l , int r){
     if(l == r){
         Tree[now].sum = read();
         Tree[now].f = Tree[now].sum == ;
         return;
     }
     init(now <<  , l , l + r >> );
     init(now <<  |  , (l + r >> ) +  , r);
     pushup(now);
 }

 void change(int now , int l , int r , int L , int R){
     if(Tree[now].f)
         return;
     if(l == r){
         Tree[now].sum = sqrt(Tree[now].sum);
         Tree[now].f = Tree[now].sum == ;
         return;
     }
      >= L)
         change(now <<  , l , l + r >>  , L , R);
      < R)
         change(now <<  |  , (l + r >> ) +  , r , L , R);
     pushup(now);
 }

 int getAns(int now , int l , int r , int L , int R){
     if(l >= L && r <= R)
         return Tree[now].sum;
     ;
      >= L)
         sum += getAns(now <<  , l , l + r >>  , L , R);
      < R)
         sum += getAns(now <<  |  , (l + r >> ) +  , r , L , R);
     return sum;
 }

 main()
 {
     ios::sync_with_stdio();
     cin.tie();
     cout.tie();
     ;
     while((N = read()) && N){
         init( ,  , N);
         cout << "Case #" << ++c << ":" << endl;
         for(int M = read() ; M ; M--)
             ){
                 int a = read() , b = read();
                 if(a > b)
                     swap(a , b);
                 change( ,  , N , a , b);
             }
             else{
                 int a = read() , b = read();
                 if(a > b)
                     swap(a , b);
                 cout << getAns( ,  , N , a , b) << endl;
             }
         cout << endl;
      }
      ;
 }

GSS4

GSS5

设左区间为$[a,b]$,右区间为$[c,d]$,满足$b \geq c$

分类讨论:

①左端点在$[a,c)$,答案为$[a,c)$的最大后缀与$[c,d]$的最大前缀

②右端点在$(b,d]$,答案为$[a,b]$的最大后缀与$(b,d]$的最大前缀

③左右端点都在$[b,c]$,答案为$[b,c]$的最大子段和

 #include<bits/stdc++.h>
 #define MAXN 10001
 using namespace std;

 inline int max(int a , int b){
     return a > b ? a : b;
 }
 inline int min(int a , int b){
     return a < b ? a : b;
 }

 struct node{
     int l , r , lMax , rMax , midMax , sum;
 }Tree[MAXN << ];
 int a[MAXN] , N , lMax , rMax , allMax;

 void init(int dir , int l , int r){
     Tree[dir].l = l;
     Tree[dir].r = r;
     if(l == r)
         Tree[dir].lMax = Tree[dir].rMax = Tree[dir].midMax = Tree[dir].sum = a[l];
     else{
         init(dir <<  , l , (l + r) >> );
         init(dir <<  |  , ((l + r) >> ) +  , r);
         Tree[dir].sum = Tree[dir << ].sum + Tree[dir <<  | ].sum;
         Tree[dir].lMax = max(Tree[dir << ].lMax , Tree[dir << ].sum + Tree[dir <<  | ].lMax);
         Tree[dir].rMax = max(Tree[dir <<  | ].rMax , Tree[dir << ].rMax + Tree[dir <<  | ].sum);
         Tree[dir].midMax = max(Tree[dir << ].rMax + Tree[dir <<  | ].lMax , max(Tree[dir << ].midMax , Tree[dir <<  | ].midMax));
     }
 }

 int findSum(int dir , int l , int r){
     if(Tree[dir].l >= l && Tree[dir].r <= r)
         return Tree[dir].sum;
     ;
     )
         sum += findSum(dir <<  , l , r);
     )
         sum += findSum(dir <<  |  , l , r);
     return sum;
 }

 void findRightMax(int dir , int l , int r){
     if(Tree[dir].l >= l && Tree[dir].r <= r){
         allMax = max(allMax , Tree[dir].rMax + rMax);
         rMax += Tree[dir].sum;
         return;
     }
     )
         findRightMax(dir <<  |  , l , r);
     )
         findRightMax(dir <<  , l , r);
 }

 void findLeftMax(int dir , int l , int r){
     if(Tree[dir].l >= l && Tree[dir].r <= r){
         allMax = max(allMax , Tree[dir].lMax + lMax);
         lMax += Tree[dir].sum;
         return;
     }
     )
         findLeftMax(dir <<  , l , r);
     )
         findLeftMax(dir <<  |  , l , r);
 }

 void findMax(int dir , int l , int r){
     if(Tree[dir].l >= l && Tree[dir].r <= r){
         allMax = max(allMax , max(Tree[dir].lMax + rMax , Tree[dir].midMax));
         rMax = max( , max(Tree[dir].sum + rMax , Tree[dir].rMax));
         return;
     }
     )
         findMax(dir <<  , l , r);
     )
         findMax(dir <<  |  , l , r);
 }

 inline int getAns(int a , int b , int c , int d){
     ;
      < c)
         t += findSum( , b +  , c - );
     if(a <= b){
         allMax = -0x7fffffff;
         rMax = ;
         findRightMax( , a , b);
         t += allMax;
     }
     if(c <= d){
         allMax = -0x7fffffff;
         lMax = ;
         findLeftMax( , c , d);
         t += allMax;
     }
     return t;
 }

 inline int work(int a , int b , int c , int d){
     c = max(a , c);
     b = min(b , d);
     if(b < c)
         return getAns(a , b , c , d);
     else{
         allMax = -0x7fffffff;
         rMax = ;
         findMax( , c , b);
         int t = allMax;
          , c , d) , getAns(c , b , b +  , d)) , t);
     }
 }

 int main(){
     int T;
     for(cin >> T ; T ; T--){
         cin >> N;
          ; i <= N ; i++)
             cin >> a[i];
         init( ,  , N);
         int M;
         for(cin >> M ; M ; M--){
             int a , b , c , d;
             cin >> a >> b >> c >> d;
             printf("%d\n" , work(a , b , c , d));
         }
     }
     ;
 }

GSS5

GSS6

维护数列削弱版本

因为$remove$的一个智障失误调了$3h$

 #include<bits/stdc++.h>
 #define root Tree[0].ch[0]
 #define lch Tree[x].ch[0]
 #define rch Tree[x].ch[1]
 #define INF 0x3f3f3f3f
 //This code is written by Itst
 using namespace std;

 inline int max(int a , int b){
     return a > b ? a : b;
 }

 inline int min(int a , int b){
     return a < b ? a : b;
 }

 inline int read(){
     ;
     ;
     char c = getchar();
     while(c != EOF && !isdigit(c)){
         if(c == '-')
             f = ;
         c = getchar();
     }
     while(c != EOF && isdigit(c)){
         a = (a << ) + (a << ) + (c ^ ');
         c = getchar();
     }
     return f ? -a : a;
 }

 ];
 inline void print(int x){
     ){
         putchar('-');
         x = -x;
     }
     if(!x)
         putchar(');
     ;
     while(x){
         output[dirN++] = x %  + ;
         x /= ;
     }
     while(dirN)
         putchar(output[--dirN]);
     putchar('\n');
 }

 ;
 struct node{
     ] , allMax , lMax , rMax , val , sum;
 }Tree[MAXN];
 int num[MAXN] , N , cntNode , y , z , w;

 inline bool son(const int& x){
     ] == x;
 }

 void pushup(int x){
     Tree[x].lMax = max(Tree[lch].lMax , Tree[lch].sum + Tree[x].val + max(Tree[rch].lMax , ));
     Tree[x].rMax = max(Tree[rch].rMax , Tree[rch].sum + Tree[x].val + max(Tree[lch].rMax , ));
     Tree[x].allMax = max(max(Tree[lch].allMax , Tree[rch].allMax) , max(Tree[lch].rMax , ) + max(Tree[rch].lMax , ) + Tree[x].val);
     Tree[x].sum = Tree[lch].sum + Tree[rch].sum + Tree[x].val;
     Tree[x].size = Tree[lch].size + Tree[rch].size + ;
 }

 inline void ZigZag(int x){
     bool f = son(x);
     y = Tree[x].fa;
     z = Tree[y].fa;
     w = Tree[x].ch[f ^ ];
     Tree[z].ch[son(y)] = x;
     Tree[x].fa = z;
     Tree[x].ch[f ^ ] = y;
     Tree[y].fa = x;
     Tree[y].ch[f] = w;
     if(w)
         Tree[w].fa = y;
     pushup(y);
 }

 inline void Splay(int x , int tar){
     while(Tree[x].fa != tar){
         if(Tree[Tree[x].fa].fa != tar)
             ZigZag(son(x) == son(Tree[x].fa) ? Tree[x].fa : x);
         ZigZag(x);
     }
     pushup(x);
 }

 void insert(int& x , int fa , int rk , int val){
     if(!x){
         x = ++cntNode;
         Tree[x].fa = fa;
         Tree[x].lMax = Tree[x].rMax = Tree[x].allMax = Tree[x].val = Tree[x].sum = val;
         Tree[x].size = ;
         Splay(x , );
         return;
     }
     if(rk > Tree[lch].size)
         insert(rch , x , rk - Tree[lch].size -  , val);
     else
         insert(lch , x , rk , val);
 }

 void getKth(int x , int rk , int tar){
     if(rk == Tree[lch].size)
         Splay(x , tar);
     else
         if(rk > Tree[lch].size)
             getKth(rch , rk - Tree[lch].size -  , tar);
         else
             getKth(lch , rk , tar);
 }

 inline void remove(int rk){
     getKth(root , rk , );
     getKth(root , rk -  , root);
     int t = root;
     root = Tree[t].ch[];
     Tree[root].ch[] = Tree[t].ch[];
     Tree[root].fa = ;
     Tree[Tree[t].ch[]].fa = root;
     pushup(Tree[t].ch[]);
 }

 inline void change(int rk , int val){
     getKth(root , rk , );
     Tree[root].val = val;
     pushup(root);
 }

 inline void query(int l , int r){
     getKth(root , l -  , );
     getKth(root , r +  , root);
     print(Tree[Tree[Tree[root].ch[]].ch[]].allMax);
 }

 inline char getc(){
     char c = getchar();
     while(!isupper(c))
         c = getchar();
     return c;
 }

 int main(){
 #ifndef ONLINE_JUDGE
     freopen("4487.in" , "r" , stdin);
     freopen("4487.out" , "w" , stdout);
 #endif
     insert(root ,  ,  , );
     insert(root ,  ,  , );
     Tree[].allMax = Tree[].allMax = Tree[].allMax = -INF;
     N = read();
      ; i <= N ; ++i)
         insert(root ,  , i , read());
     int a , b;
     for(register int M = read() ; M ; --M){
         ].fa)
             Tree[].fa = ;
         switch(getc()){
         case 'I':
             a = read();
             b = read();
             insert(root ,  , a , b);
             break;
         case 'D':
             remove(read());
             break;
         case 'R':
             a = read();
             b = read();
             change(a , b);
             break;
         case 'Q':
             a = read();
             b = read();
             query(a , b);
             break;
         }
     }
     ;
 }

GSS6

GSS7

树剖+最大子段和

实际上也没什么区别只是莫名码量大了非常多

 #include<bits/stdc++.h>
 #define MAXN 100001
 using namespace std;
 inline int read(){
     ;
     ;
     char c = getchar();
     while(!isdigit(c)){
         if(c == '-')
             f = ;
         c = getchar();
     }
     while(isdigit(c)){
         a = (a << ) + (a << ) + (c ^ ');
         c = getchar();
     }
     return f ? -a : a;
 }
 ];
 inline void print(int x){
     ;
     )
         fwrite( , stdout);
     else{
         ){
             x = -x;
             fwrite( , stdout);
         }
         while(x){
                output[--dirN] = x %  + ;
             x /= ;
         }
         fwrite(output + dirN ,  , strlen(output + dirN) , stdout);
     }
     fwrite( ,  , stdout);
 }

 struct node{
     int l , r , lMax , rMax , midMax , sum , mark;
 }Tree[MAXN << ];
 struct Edge{
     int end , upEd;
 }Ed[MAXN << ];
 int val[MAXN] , head[MAXN] , size[MAXN] , son[MAXN] , fa[MAXN] , dep[MAXN];
 int top[MAXN] , ind[MAXN] , rk[MAXN] , N , ts , cntEd , allMax , lMax , rMax;

 inline void addEd(int a , int b){
     Ed[++cntEd].end = b;
     Ed[cntEd].upEd = head[a];
     head[a] = cntEd;
 }

 void dfs1(int dir , int father){
     size[dir] = ;
     dep[dir] = dep[fa[dir] = father] + ;
     for(int i = head[dir] ; i ; i = Ed[i].upEd)
         if(!dep[Ed[i].end]){
             dfs1(Ed[i].end , dir);
             size[dir] += size[Ed[i].end];
             if(size[son[dir]] < size[Ed[i].end])
                 son[dir] = Ed[i].end;
         }
 }

 void dfs2(int dir , int t){
     top[dir] = t;
     rk[ind[dir] = ++ts] = dir;
     if(!son[dir])
         return;
     dfs2(son[dir] , t);
     for(int i = head[dir] ; i ; i = Ed[i].upEd)
         if(Ed[i].end != son[dir] && Ed[i].end != fa[dir])
             dfs2(Ed[i].end , Ed[i].end);
 }

 inline void pushup(int dir){
     Tree[dir].lMax = max(Tree[dir << ].lMax , Tree[dir << ].sum + Tree[dir <<  | ].lMax);
     Tree[dir].rMax = max(Tree[dir <<  | ].rMax , Tree[dir << ].rMax + Tree[dir <<  | ].sum);
     Tree[dir].sum = Tree[dir << ].sum + Tree[dir <<  | ].sum;
     Tree[dir].midMax = max(max(Tree[dir << ].midMax , Tree[dir <<  | ].midMax) , Tree[dir << ].rMax + Tree[dir <<  | ].lMax);
 }

 inline void pushdown(int dir){
     ){
         Tree[dir << ].lMax = Tree[dir << ].rMax = Tree[dir << ].midMax = max(Tree[dir << ].sum = Tree[dir].mark * (Tree[dir << ].r - Tree[dir << ].l + ) , );
         Tree[dir <<  | ].lMax = Tree[dir <<  | ].rMax = Tree[dir <<  | ].midMax = max(Tree[dir <<  | ].sum = Tree[dir].mark * (Tree[dir <<  | ].r - Tree[dir <<  | ].l + ) , );
         Tree[dir << ].mark = Tree[dir <<  | ].mark = Tree[dir].mark;
         Tree[dir].mark = -;
     }
 }

 void init(int dir , int l , int r){
     Tree[dir].l = l;
     Tree[dir].r = r;
     Tree[dir].mark = -;
     if(l == r)
         Tree[dir].lMax = Tree[dir].rMax = Tree[dir].midMax = max(Tree[dir].sum = val[rk[l]] , );
     else{
         init(dir <<  , l , (l + r) >> );
         init(dir <<  |  , ((l + r) >> ) +  , r);
         pushup(dir);
     }
 }

 void change(int dir , int l , int r , int val){
     if(Tree[dir].l >= l && Tree[dir].r <= r){
         Tree[dir].lMax = Tree[dir].rMax = Tree[dir].midMax = max(Tree[dir].sum = (Tree[dir].mark = val) * (Tree[dir].r - Tree[dir].l + ) , );
         return;
     }
     pushdown(dir);
     )
         change(dir <<  , l , r , val);
     )
         change(dir <<  |  , l , r , val);
     pushup(dir);
 }

 void askLeft(int dir , int l , int r){
     if(Tree[dir].l >= l && Tree[dir].r <= r){
         allMax = max(allMax , max(lMax + Tree[dir].rMax , Tree[dir].midMax));
         lMax = max(Tree[dir].lMax , Tree[dir].sum + lMax);
         return;
     }
     pushdown(dir);
     )
         askLeft(dir <<  |  , l , r);
     )
         askLeft(dir <<  , l , r);
 }

 void askRight(int dir , int l , int r){
     if(Tree[dir].l >= l && Tree[dir].r <= r){
         allMax = max(allMax , max(rMax + Tree[dir].rMax , Tree[dir].midMax));
         rMax = max(Tree[dir].lMax , Tree[dir].sum + rMax);
         return;
     }
     pushdown(dir);
     )
         askRight(dir <<  |  , l , r);
     )
         askRight(dir <<  , l , r);
 }

 inline void work1(int l , int r , int val){
     int tl = top[l] , tr = top[r];
     while(tl != tr)
         if(dep[tl] >= dep[tr]){
             change( , ind[tl] , ind[l] , val);
             tl = top[l = fa[tl]];
         }
         else{
             change( , ind[tr] , ind[r] , val);
             tr = top[r = fa[tr]];
         }
     if(ind[l] < ind[r])
         change( , ind[l] , ind[r] , val);
     else
         change( , ind[r] , ind[l] , val);
 }

 inline void work2(int l , int r){
     allMax = lMax = rMax = ;
     int tl = top[l] , tr = top[r];
     while(tl != tr)
         if(dep[tl] >= dep[tr]){
             askLeft( , ind[tl] , ind[l]);
             tl = top[l = fa[tl]];
         }
         else{
             askRight( , ind[tr] , ind[r]);
             tr = top[r = fa[tr]];
         }
     if(ind[l] < ind[r])
         askRight( , ind[l] , ind[r]);
     else
         askLeft( , ind[r] , ind[l]);
     print(max(allMax , lMax + rMax));
 }

 int main(){
     N = read();
      ; i <= N ; i++)
         val[i] = read();
      ; i < N ; i++){
         int a = read() , b = read();
         addEd(a , b);
         addEd(b , a);
     }
     dfs1( , );
     dfs2( , );
     init( ,  , N);
     for(int Q = read() ; Q ; Q--){
         int a = read() , b = read() , c = read();
         )
             work1(b , c , read());
         else
             work2(b , c);
     }
     ;
 }

GSS7

上一篇:centos 安装


下一篇:perl出现Global symbol "" requires explicit package name at ""的错误