zoukankan      html  css  js  c++  java
  • poj 3468 A Simple Problem with Integers 区间更新与询问 Splay简单应用

    Splay 的属性  

    1 struct Splay{
    2     int rt, cnt;
    3     int ch[N][2], pre[N], sz[N];
    4     LL sum[N], add[N], val[N];
    5 }

    Splay 的操作主要集中在 

      1. Rotate( x, d )    旋转分为 左旋(d=0), 右旋(d=1)

      2. Splay( x, goal ) 将节点x 旋转到 节点goal下

      3. Rotate_To( k, goal ) 将左数第k个节点旋转到 节点goal 下

     1 void rotate(int x,int d){
     2         int y = pre[x];
     3         push_down(y); push_down(x);    
     4         ch[y][d^1] = ch[x][d];
     5         pre[ ch[x][d] ] = y; 
     6         pre[x] = pre[y];
     7         if( pre[y] ) ch[ pre[y] ][ ch[pre[y]][1] == y ]  = x;
     8         ch[x][d] = y;
     9         pre[y] = x;
    10         push_up(y); //push_up(x);
    11     }
     1 void splay(int x,int goal){
     2         // satisfy the x under the goal;    
     3         push_down(x);    
     4         while( pre[x] != goal ){
     5             int y = pre[x];
     6             if( pre[y] == goal ) rotate( x, ch[y][0] == x );
     7             else{
     8                 int z = pre[y];
     9                 int d1 = ch[z][0]==y, d2 = ch[y][0]==x;
    10                 if( d1 == d2 ) rotate( y, d1 ), rotate( x, d2 );
    11                 else    rotate( x, d2 ), rotate( x, d1 );
    12             }    
    13         }    
    14         push_up(x);
    15         if(goal == 0) rt = x;
    16     }    
     1 void rotate_to(int k, int goal){ 
     2         // find the x of it's left-child size is k 
     3         // because of we add two virtual point    
     4         int x = rt;
     5         while( sz[ ch[x][0] ] != k ){
     6             if( sz[ ch[x][0] ] > k ) x = ch[x][0];
     7             else    k -= (sz[ ch[x][0] ]+1), x = ch[x][1];
     8             push_down(x);
     9         }
    10     //    printf("x is %d\n", x);    
    11         splay(x,goal);    
    12     }

    完整解题代码:

    View Code
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    
    #define keytree ch[ ch[rt][1] ][0]
    const int N = 1e5+10;
    typedef long long LL;
    int tmp[N];
    
    struct Splay{
        int rt, cnt;
        int ch[N][2], pre[N], sz[N];
        LL sum[N], add[N], val[N];
        //Splay Operator
        void rotate(int x,int d){
            int y = pre[x];
            push_down(y); push_down(x);    
            ch[y][d^1] = ch[x][d];
            pre[ ch[x][d] ] = y; 
            pre[x] = pre[y];
            if( pre[y] ) ch[ pre[y] ][ ch[pre[y]][1] == y ]  = x;
            ch[x][d] = y;
            pre[y] = x;
            push_up(y); //push_up(x);
        }
        void splay(int x,int goal){
            // satisfy the x under the goal;    
            push_down(x);    
            while( pre[x] != goal ){
                int y = pre[x];
                if( pre[y] == goal ) rotate( x, ch[y][0] == x );
                else{
                    int z = pre[y];
                    int d1 = ch[z][0]==y, d2 = ch[y][0]==x;
                    if( d1 == d2 ) rotate( y, d1 ), rotate( x, d2 );
                    else    rotate( x, d2 ), rotate( x, d1 );
                }    
            }    
            push_up(x);
            if(goal == 0) rt = x;
        }    
        void rotate_to(int k, int goal){ 
            // find the x of it's left-child size is k 
            // because of we add two virtual point    
            int x = rt;
            while( sz[ ch[x][0] ] != k ){
                if( sz[ ch[x][0] ] > k ) x = ch[x][0];
                else    k -= (sz[ ch[x][0] ]+1), x = ch[x][1];
                push_down(x);
            }
        //    printf("x is %d\n", x);    
            splay(x,goal);    
        }
        //Tree Operator
        void NewNode(int &x,int c){
            x = ++cnt;
            ch[x][0]=ch[x][1]=pre[x]=0;
            sum[x]=val[x]=c;
            add[x] = 0; sz[x] = 0;
        }    
        void push_up(int x){
            if( x == 0 ) return;    
            sum[x] = val[x] + sum[ch[x][0]] + sum[ch[x][1]];
            sz[x] = 1 + sz[ch[x][0]] + sz[ch[x][1]];
        }
        void push_down(int x){
            if( add[x] ){
                val[x] += add[x];    
                add[ch[x][0]] += add[x]; add[ch[x][1]] += add[x];
                sum[ch[x][0]] += 1LL*sz[ch[x][0]]*add[x];
                sum[ch[x][1]] += 1LL*sz[ch[x][1]]*add[x];    
                add[x] = 0;
            }    
        }
        void build(int &x, int l,int r,int f){
            if( l > r ) return;
            int m = (l+r)>>1;
            NewNode( x, tmp[m] );
            pre[x] = f;
            build( ch[x][0], l, m-1, x ); build( ch[x][1], m+1, r, x );
            push_up( x );    
        }
        void update(int l,int r,int c){
            rotate_to( l-1, 0 );
            rotate_to( r+1, rt );
            add[keytree] += c;
            sum[keytree] += 1LL*sz[keytree]*c;
        }
        LL query(int l,int r){
            rotate_to( l-1, 0 ); 
            rotate_to( r+1, rt); 
            return sum[keytree];
        }
        void init(int n){
            rt = cnt = 0;
            ch[0][0]=ch[0][1]=pre[0]=sz[0]=val[0]=sum[0]=add[0]=0;
            //init the Null Node; 
            NewNode( rt, 0); NewNode( ch[rt][1], 0 );
            pre[ ch[rt][1] ] = rt;
            build( keytree, 0, n-1, ch[rt][1] );
            push_up( ch[rt][1] ), push_up( rt );
        //    print(rt);
        }
        void print(int x){
            if(x==0) printf("Tree is NULL!\n");
            if( ch[x][0] ) print(ch[x][0]);
            printf("cur:%d lch:%d rch:%d sum:%lld sz:%d val:%lld\n",
                    x,ch[x][0],ch[x][1],sum[x],sz[x],val[x]);
            if( ch[x][1] ) print(ch[x][1]);
        }
    }spt;
    int main(){
        int n, m;
        while( scanf("%d%d",&n,&m) != EOF){
            for(int i = 0; i < n; i++) scanf("%d", &tmp[i] );
            spt.init(n);    
            char op[5]; int a, b, c;
            for(int i = 0; i < m; i++){
                scanf("%s", op );
                if( op[0] == 'C' ){
                    scanf("%d%d%d",&a,&b,&c);
                    spt.update( a, b, c );
                }
                else{
                    scanf("%d%d",&a,&b);
                    printf("%lld\n", spt.query(a,b) );
                }
            }
        }
        return 0;
    }
    11486939 yefeng1627 3468 Accepted 4488K 3766MS C++ 3275B 2013-04-17 12:14:30

    线段树代码:

    View Code
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    #define lch rt<<1,l,m
    #define rch rt<<1|1,m+1,r
    
    const int N = 111111;
    typedef long long LL;
    
    LL sum[N<<2], add[N<<2];
    int n;
    
    void push_up(int rt){
        sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    }
    void push_down(int rt,int len){
        if( add[rt] ){
            add[rt<<1] += add[rt]; add[rt<<1|1] += add[rt];
            sum[rt<<1] += 1LL*(len-(len>>1))*add[rt];
            sum[rt<<1|1] += 1LL*(len>>1)*add[rt];
            add[rt] = 0;
        }
    }
    void build(int rt,int l,int r){
        sum[rt] = add[rt] = 0;
        if( l == r ){
            scanf("%lld", &sum[rt] ); return;    
        }
        int m = (l+r)>>1;
        build(lch), build(rch);
        push_up(rt);
    }
    void update(int rt,int l,int r,int a,int b,int c){
        if( a <= l && r <= b ){
            sum[rt] += 1LL*(r-l+1)*c;
            add[rt] += c;
            return;
        }
        push_down(rt,r-l+1);
        int m = (l+r)>>1;
        if( a <= m ) update(lch,a,b,c);
        if( m <  b ) update(rch,a,b,c);
        push_up(rt); // After update ,should push_up to parent.
    }
    LL query(int rt,int l,int r,int a,int b){
        if( a <= l && r <= b ) return sum[rt];
        push_down(rt,r-l+1);
        int m = (l+r)>>1;
        LL res = 0;
        if( a <= m ) res += query(lch,a,b);
        if( m <  b ) res += query(rch,a,b);
        return res;
    }
    
    int main(){
        int m;    
        while( scanf("%d%d", &n,&m) != EOF){
            build( 1, 1, n );
            char op[5]; int a, b, c;
            for(int i = 0; i < m; i++){
                scanf("%s", op );
                if( op[0] == 'C' ){
                    scanf("%d%d%d",&a,&b,&c);
                    update(1,1,n,a,b,c);
                }
                else{
                    scanf("%d%d", &a,&b);    
                    printf("%lld\n", query(1,1,n,a,b) );    
                }    
            }
        }                
        return 0;
    }
    11487052 yefeng1627 3468 Accepted 4520K 2641MS G++ 1559B 2013-04-17 12:41:41
  • 相关阅读:
    迭代器实现斐波那契数列
    type 创建类,赋予类静态方法等
    使用types库修改函数
    使用property取代getter和setter方法
    pdb 进行调试
    nonlocal 访问变量
    timeit_list操作测试
    metaclass 拦截类的创建,并返回
    isinstance方法判断可迭代和迭代器
    苹果cms10 官方QQ微信防红防封代码
  • 原文地址:https://www.cnblogs.com/yefeng1627/p/3025996.html
Copyright © 2011-2022 走看看