树状数组

转载 来自http://blog.csdn.net/lawrence_jang/article/details/8054173
14、树状数组
(1)、单点增减+区间求和
思路:C[x]表示该点的元素:sum(x)=C[1]+C[2]+……C[x]
  1. int arr[MAXN];  
  2. inline int sum(int x){int res=0;while(x)res+=arr[x],x-=lowbit(x);return res;}  
  3. inline void add(int x,int n){while(x<MAXN)arr[x]+=n,x+=lowbit(x);}  
  4. inline int query(int x,int y){return sum(y)-sum(x-1);}  
int arr[MAXN];
inline int sum(int x){int res=0;while(x)res+=arr[x],x-=lowbit(x);return res;}
inline void add(int x,int n){while(x<MAXN)arr[x]+=n,x+=lowbit(x);}
inline int query(int x,int y){return sum(y)-sum(x-1);}

(2)、区间增减+单点查询
思路:C[x]表示该点元素与左边元素的差值:num[x]=C[1]+C[2]+……C[x]
  1. int arr[MAXN]  
  2. inline int sum(int x){int res=0;while(x)res+=arr[x],x-=lowbit(x);return res;}  
  3. inline void add(int x,int n){while(x<MAXN)arr[x]+=n,x+=lowbit(x);}  
  4. inline int update(int x,int y,int n){add(x,n);add(y+1,-n);}  
int arr[MAXN]
inline int sum(int x){int res=0;while(x)res+=arr[x],x-=lowbit(x);return res;}
inline void add(int x,int n){while(x<MAXN)arr[x]+=n,x+=lowbit(x);}
inline int update(int x,int y,int n){add(x,n);add(y+1,-n);}


(3)、区间增减+区间查询
思路:C1[x]表示该点元素与左边的差值,C2[x]表示的是x*C[x]
  1. sum(sum(C[j],j<=i)i<=x)  
  2. = x*C[1]+(x-1)*C[2]+……+C[x]  
  3. =(x+1)*sum(C[i],i<=x)-sum(i*C[i],i<=x);  
sum(sum(C[j],j<=i)i<=x)
= x*C[1]+(x-1)*C[2]+……+C[x]
=(x+1)*sum(C[i],i<=x)-sum(i*C[i],i<=x);


则可以想到用C1[x]维护C[x]的值,C2[x]维护x*C[X]的值
  1. template <typename X>  
  2. struct tree_array{  
  3.     struct tree_array_single{  
  4.         X arr[MAXN];  
  5.         void add(int x,X n){while(x<=N)arr[x]+=n,x+=lowbit(x);}  
  6.         X sum(int x){X sum=0;while(x)sum+=arr[x],x-=lowbit(x);return sum;}  
  7.     }T1,T2;  
  8.     void reset(){CLR(T1.arr,0); CLR(T2.arr,0);}  
  9.     void add(int x,X n){T1.add(x,n);T2.add(x,x*n);}  
  10.     void update(int L,int R,int n){add(L,n);add(R+1,-n);}  
  11.     X sum(int x){return (x+1)*T1.sum(x)-T2.sum(x);}  
  12.     X query(int L,int R){return sum(R)-sum(L-1);}  
  13. };  
template <typename X>
struct tree_array{
    struct tree_array_single{
        X arr[MAXN];
        void add(int x,X n){while(x<=N)arr[x]+=n,x+=lowbit(x);}
        X sum(int x){X sum=0;while(x)sum+=arr[x],x-=lowbit(x);return sum;}
    }T1,T2;
    void reset(){CLR(T1.arr,0); CLR(T2.arr,0);}
    void add(int x,X n){T1.add(x,n);T2.add(x,x*n);}
    void update(int L,int R,int n){add(L,n);add(R+1,-n);}
    X sum(int x){return (x+1)*T1.sum(x)-T2.sum(x);}
    X query(int L,int R){return sum(R)-sum(L-1);}
};


15、多维树状数组
①单点增减(add) + 矩形求和(query) 
②矩形增减(update) + 单点求值(sum)
  1. int arr[MAXN][MAXN]  
  2. inline void add(int x,int y,int n) {  
  3.     for(int i=x;i<MAXN;i+=lowbit(i))  
  4.         for(int j=y;j<MAXN;j+=lowbit(j))  
  5.             arr[i][j]+=n;  
  6. }  
  7. inline int sum(int x,int y){  
  8.     int res=0;  
  9.     for(int i=x;i;i-=lowbit(i))  
  10.         for(int j=y;j;j-=lowbit(j))  
  11.             res+=arr[i][j];  
  12.     return res;  
  13. }  
  14. inline int query(int L,int B,int R,int T) {  
  15.     return sum(R,T)+sum(L-1,B-1)-sum(R,B-1)-sum(L-1,T);  
  16. }  
  17. inline void update(int L,int B,int R,int T,int n){  
  18.     update(L,B,n);update(L,T+1,n);update(R+1,B,n);update(R+1,T+1,n);  
  19. }  
int arr[MAXN][MAXN]
inline void add(int x,int y,int n) {
    for(int i=x;i<MAXN;i+=lowbit(i))
        for(int j=y;j<MAXN;j+=lowbit(j))
            arr[i][j]+=n;
}
inline int sum(int x,int y){
    int res=0;
    for(int i=x;i;i-=lowbit(i))
        for(int j=y;j;j-=lowbit(j))
            res+=arr[i][j];
    return res;
}
inline int query(int L,int B,int R,int T) {
    return sum(R,T)+sum(L-1,B-1)-sum(R,B-1)-sum(L-1,T);
}
inline void update(int L,int B,int R,int T,int n){
    update(L,B,n);update(L,T+1,n);update(R+1,B,n);update(R+1,T+1,n);
}


③矩形增减(update)+ 矩形求和(query)
  1. template<typename X>  
  2. class tree_array{  
  3.     struct tree_array_single{  
  4.         X arr[MAXN][MAXN];  
  5.         void add(int x,int y,X n){  
  6.             for(int i=x; i<MAXN; i+=lowbit(i))  
  7.                 for(int j=y; j<MAXN; j+=lowbit(j))  
  8.                     arr[i][j]+=n;  
  9.         }  
  10.         X sum(int x,int y){  
  11.             X res=0;  
  12.             for(int i=x; i; i-=lowbit(i))  
  13.                 for(int j=y; j; j-=lowbit(j))  
  14.                     res+=arr[i][j];  
  15.             return res;  
  16.         }  
  17.     } T1,T2,T3,T4;  
  18.     void add(int x,int y,int n){  
  19.         T1.add(x,y,n);T2.add(x,y,y*n);T3.add(x,y,x*n);T4.add(x,y,x*y*n);  
  20.     }  
  21.     X sum(int x,int y){  
  22.     return (x+1)*(y+1)*T1.sum(x,y)-(x+1)*T2.sum(x,y)-(y+1)*T3.sum(x,y)+T4.sum(x,y);}  
  23. public:  
  24.     void init(){CLR(T1.arr,0);CLR(T2.arr,0);CLR(T3.arr,0);CLR(T4.arr,0);}  
  25.     void update(int L,int B,int R,int T,int n){  
  26.         add(L,B,n);add(L,T+1,-n);add(R+1,B,-n);add(R+1,T+1,n);  
  27.     }  
  28.     X query(int L,int B,int R,int T){  
  29.         return sum(R,T)-sum(L-1,T)-sum(R,B-1)+sum(L-1,B-1);  
  30.     }  
  31. };  
template<typename X>
class tree_array{
    struct tree_array_single{
        X arr[MAXN][MAXN];
        void add(int x,int y,X n){
            for(int i=x; i<MAXN; i+=lowbit(i))
                for(int j=y; j<MAXN; j+=lowbit(j))
                    arr[i][j]+=n;
        }
        X sum(int x,int y){
            X res=0;
            for(int i=x; i; i-=lowbit(i))
                for(int j=y; j; j-=lowbit(j))
                    res+=arr[i][j];
            return res;
        }
    } T1,T2,T3,T4;
    void add(int x,int y,int n){
        T1.add(x,y,n);T2.add(x,y,y*n);T3.add(x,y,x*n);T4.add(x,y,x*y*n);
    }
    X sum(int x,int y){
    return (x+1)*(y+1)*T1.sum(x,y)-(x+1)*T2.sum(x,y)-(y+1)*T3.sum(x,y)+T4.sum(x,y);}
public:
    void init(){CLR(T1.arr,0);CLR(T2.arr,0);CLR(T3.arr,0);CLR(T4.arr,0);}
    void update(int L,int B,int R,int T,int n){
        add(L,B,n);add(L,T+1,-n);add(R+1,B,-n);add(R+1,T+1,n);
    }
    X query(int L,int B,int R,int T){
        return sum(R,T)-sum(L-1,T)-sum(R,B-1)+sum(L-1,B-1);
    }
};


④单点增减(add) + 立方体求和(query)
⑤立方体增减(update) + 单点求值(sum)
  1. int arr[MAXN][MAXN][MAXN];  
  2. inline int sum(int x,int y,int z){  
  3.     int res=0;  
  4.     for(int i=x;i;i-=lowbit(i))  
  5.         for(int j=y;j;j-=lowbit(j))  
  6.             for(int k=z;k;k-=lowbit(k))  
  7.                 res^=arr[i][j][k];  
  8.     return res;  
  9. }  
  10. inline void add(int x,int y,int z,int n){   
  11.     for(int i=x;i<MAXN;i+=lowbit(i))  
  12.         for(int j=y;j<MAXN;j+=lowbit(j))  
  13.             for(int k=z;k<MAXN;k+=lowbit(k))  
  14.                 arr[i][j][k]+=n;  
  15. }  
  16. inline void update(int x1,int y1,int z1,int x2,int y2,int z2,int n){  
  17. add(x1,y1,z1,n);  
  18. add(x2+1,y1,z1,-n);add(x1,y2+1,z1,-n);add(x1,y1,z2+1,-n);  
  19. add(x2+1,y2+1,z1,n);add(x2+1,y1,z2+1,n);add(x1,y2+1,z2+1,n);  
  20. add(x2+1,y2+1,z2+1,-n);  
  21. }  
  22. inline int query(int x1,int y1,int z1,int x2,int y2,int z2){  
  23.     return sum(x2,y2,z2)  
  24.     -sum(x2,y2,z1-1)-sum(x2,y1-1,z2)-sum(x1-1,y2,z2)  
  25.     +sum(x2,y1-1,z1-1)+sum(x1-1,y2,z1-1)+sum(x1-1,y1-1,z2)  
  26.     -sum(x1-1,y1-1,z1-1);  
  27. }  
int arr[MAXN][MAXN][MAXN];
inline int sum(int x,int y,int z){
    int res=0;
    for(int i=x;i;i-=lowbit(i))
        for(int j=y;j;j-=lowbit(j))
            for(int k=z;k;k-=lowbit(k))
                res^=arr[i][j][k];
    return res;
}
inline void add(int x,int y,int z,int n){ 
    for(int i=x;i<MAXN;i+=lowbit(i))
        for(int j=y;j<MAXN;j+=lowbit(j))
            for(int k=z;k<MAXN;k+=lowbit(k))
                arr[i][j][k]+=n;
}
inline void update(int x1,int y1,int z1,int x2,int y2,int z2,int n){
add(x1,y1,z1,n);
add(x2+1,y1,z1,-n);add(x1,y2+1,z1,-n);add(x1,y1,z2+1,-n);
add(x2+1,y2+1,z1,n);add(x2+1,y1,z2+1,n);add(x1,y2+1,z2+1,n);
add(x2+1,y2+1,z2+1,-n);
}
inline int query(int x1,int y1,int z1,int x2,int y2,int z2){
    return sum(x2,y2,z2)
    -sum(x2,y2,z1-1)-sum(x2,y1-1,z2)-sum(x1-1,y2,z2)
    +sum(x2,y1-1,z1-1)+sum(x1-1,y2,z1-1)+sum(x1-1,y1-1,z2)
    -sum(x1-1,y1-1,z1-1);
}


⑥立方体增减(update) + 立方体求和(query)///随便写写……复杂度较高
  1. template<typename X>  
  2. class tree_array_Cube{  
  3.     struct tree_array_single{  
  4.         X arr[MAXN][MAXN][MAXN];  
  5.         X sum(int x,int y,int z){  
  6.             X res=0;  
  7.             for(int i=x;i;i-=lowbit(i))  
  8.                 for(int j=y;j;j-=lowbit(j))  
  9.                     for(int k=z;k;k-=lowbit(k))  
  10.                         res+=arr[i][j][k];  
  11.             return res;  
  12.         }  
  13.         void add(int x,int y,int z,X n){  
  14.             for(int i=x;i<MAXN;i+=lowbit(i))  
  15.                 for(int j=y;j<MAXN;j+=lowbit(j))  
  16.                     for(int k=z;k<MAXN;k+=lowbit(k))  
  17.                         arr[i][j][k]+=n;  
  18.         }  
  19.     }T1,T2,T3,T4,T5,T6,T7,T8;  
  20.     void add(int x,int y,int z,X n){  
  21.         T1.add(x,y,z,n);  
  22.         T2.add(x,y,z,x*n);T3.add(x,y,z,y*n);T4.add(x,y,z,z*n);  
  23.         T5.add(x,y,z,x*y*n);T6.add(x,y,z,y*z*n);T7.add(x,y,z,x*z*n);  
  24.         T8.add(x,y,z,x*y*z*n);  
  25.     }  
  26.     X sum(int x,int y,int z){  
  27.         return (x+1)*(y+1)*(z+1)*T1.sum(x,y,z)  
  28.         -(y+1)*(z+1)*T2.sum(x,y,z)-(x+1)*(z+1)*T3.sum(x,y,z)-(x+1)*(y+1)*T4.sum(x,y,z)  
  29.         +(z+1)*T5.sum(x,y,z)+(x+1)*T6.sum(x,y,z)+(y+1)*T7.sum(x,y,z)-T8.sum(x,y,z);  
  30.     }  
  31. public:  
  32.     void init(){  
  33.         CLR(T1.arr,0);CLR(T2.arr,0);CLR(T3.arr,0);CLR(T4.arr,0);  
  34.         CLR(T5.arr,0);CLR(T6.arr,0);CLR(T7.arr,0);CLR(T8.arr,0);  
  35.     }  
  36.     void update(int x1,int y1,int z1,int x2,int y2,int z2,X n){  
  37.         add(x1,y1,z1,n);  
  38.         add(x2+1,y1,z1,-n);add(x1,y2+1,z1,-n); add(x1,y1,z2+1,-n);  
  39.         add(x2+1,y2+1,z1,n);add(x2+1,y1,z2+1,n);add(x1,y2+1,z2+1,n);  
  40.         add(x2+1,y2+1,z2+1,-n);  
  41.     }  
  42.     X query(int x1,int y1,int z1,int x2,int y2,int z2){  
  43.         return sum(x2,y2,z2)  
  44.         -sum(x2,y2,z1-1)-sum(x2,y1-1,z2)-sum(x1-1,y2,z2)  
  45.         +sum(x2,y1-1,z1-1)+sum(x1-1,y2,z1-1)+sum(x1-1,y1-1,z2)  
  46.         -sum(x1-1,y1-1,z1-1);  
  47.     }  
  48. };  
template<typename X>
class tree_array_Cube{
    struct tree_array_single{
        X arr[MAXN][MAXN][MAXN];
        X sum(int x,int y,int z){
            X res=0;
            for(int i=x;i;i-=lowbit(i))
                for(int j=y;j;j-=lowbit(j))
                    for(int k=z;k;k-=lowbit(k))
                        res+=arr[i][j][k];
            return res;
        }
        void add(int x,int y,int z,X n){
            for(int i=x;i<MAXN;i+=lowbit(i))
                for(int j=y;j<MAXN;j+=lowbit(j))
                    for(int k=z;k<MAXN;k+=lowbit(k))
                        arr[i][j][k]+=n;
        }
    }T1,T2,T3,T4,T5,T6,T7,T8;
    void add(int x,int y,int z,X n){
        T1.add(x,y,z,n);
        T2.add(x,y,z,x*n);T3.add(x,y,z,y*n);T4.add(x,y,z,z*n);
        T5.add(x,y,z,x*y*n);T6.add(x,y,z,y*z*n);T7.add(x,y,z,x*z*n);
        T8.add(x,y,z,x*y*z*n);
    }
    X sum(int x,int y,int z){
        return (x+1)*(y+1)*(z+1)*T1.sum(x,y,z)
        -(y+1)*(z+1)*T2.sum(x,y,z)-(x+1)*(z+1)*T3.sum(x,y,z)-(x+1)*(y+1)*T4.sum(x,y,z)
        +(z+1)*T5.sum(x,y,z)+(x+1)*T6.sum(x,y,z)+(y+1)*T7.sum(x,y,z)-T8.sum(x,y,z);
    }
public:
    void init(){
        CLR(T1.arr,0);CLR(T2.arr,0);CLR(T3.arr,0);CLR(T4.arr,0);
        CLR(T5.arr,0);CLR(T6.arr,0);CLR(T7.arr,0);CLR(T8.arr,0);
    }
    void update(int x1,int y1,int z1,int x2,int y2,int z2,X n){
        add(x1,y1,z1,n);
        add(x2+1,y1,z1,-n);add(x1,y2+1,z1,-n); add(x1,y1,z2+1,-n);
        add(x2+1,y2+1,z1,n);add(x2+1,y1,z2+1,n);add(x1,y2+1,z2+1,n);
        add(x2+1,y2+1,z2+1,-n);
    }
    X query(int x1,int y1,int z1,int x2,int y2,int z2){
        return sum(x2,y2,z2)
        -sum(x2,y2,z1-1)-sum(x2,y1-1,z2)-sum(x1-1,y2,z2)
        +sum(x2,y1-1,z1-1)+sum(x1-1,y2,z1-1)+sum(x1-1,y1-1,z2)
        -sum(x1-1,y1-1,z1-1);
    }
};


16、树状数组—区间最大值
  1. inline void init()  
  2. {  
  3.     CLR(arr,0);  
  4.     for(int i=1;i<=N;++i)  
  5.         for(int j=i;j<=N&&arr[j]<num[i];j+=lowbit(j))  
  6.             arr[j]=num[i];  
  7. }  
  8. inline int query(int L,int R)  
  9. {  
  10.     int res=0;  
  11.     for(–L;L<R;){  
  12.         if(R-lowbit(R)>=L){res=max(res,arr[R]);R-=lowbit(R);}  
  13.         else{res=max(res,num[R]);–R;}  
  14.     }  
  15.     return res;  
  16. }  
  17. inline void update(int x,int val)  
  18. {  
  19.     int ori=num[x];  
  20.     num[x]=val;  
  21.     if(val>=ori)  
  22.         for(int i=x;i<=N&&arr[i]<val;i+=lowbit(i))  
  23.             arr[i]=val;  
  24.     else{  
  25.         for(int i=x;i<=N&&arr[i]==ori;i+=lowbit(i))  
  26.         {  
  27.             arr[i]=val;  
  28.             for(int j=lowbit(i)>>1;j;j>>=1)  
  29.                 arr[i]=max(arr[i],arr[i-j]);  
  30.         }  
  31.     }  
  32. }  
inline void init()
{
    CLR(arr,0);
    for(int i=1;i<=N;++i)
        for(int j=i;j<=N&&arr[j]<num[i];j+=lowbit(j))
            arr[j]=num[i];
}
inline int query(int L,int R)
{
    int res=0;
    for(--L;L<R;){
        if(R-lowbit(R)>=L){res=max(res,arr[R]);R-=lowbit(R);}
        else{res=max(res,num[R]);--R;}
    }
    return res;
}
inline void update(int x,int val)
{
    int ori=num[x];
    num[x]=val;
    if(val>=ori)
        for(int i=x;i<=N&&arr[i]<val;i+=lowbit(i))
            arr[i]=val;
    else{
        for(int i=x;i<=N&&arr[i]==ori;i+=lowbit(i))
        {
            arr[i]=val;
            for(int j=lowbit(i)>>1;j;j>>=1)
                arr[i]=max(arr[i],arr[i-j]);
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值