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);}  
 

(2)、区间增减+单点查询 

思路:C[x]表示该点元素与左边元素的差值:num[x]=C[1]+C[2]+……C[x] 

 
   [cpp]  
   view plain 
    copy 
   
 
   
 
    print 
   ? 
   
 
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);}  
 


(3)、区间增减+区间查询 

思路:C1[x]表示该点元素与左边的差值,C2[x]表示的是x*C[x] 

 
   [cpp]  
   view plain 
    copy 
   
 
   
 
    print 
   ? 
   
 
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);  
 


则可以想到用C1[x]维护C[x]的值,C2[x]维护x*C[X]的值 

 
   [cpp]  
   view plain 
    copy 
   
 
   
 
    print 
   ? 
   
 
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. 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. int x){return (x+1)*T1.sum(x)-T2.sum(x);}  
12. int L,int R){return sum(R)-sum(L-1);}  
13. };  
 


15、多维树状数组 

①单点增减(add) + 矩形求和(query)  

②矩形增减(update) + 单点求值(sum) 

 
   [cpp]  
   view plain 
    copy 
   
 
   
 
    print 
   ? 
   
 
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. }  
 


③矩形增减(update)+ 矩形求和(query) 

 
   [cpp]  
   view plain 
    copy 
   
 
   
 
    print 
   ? 
   
 
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. 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. 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. 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. };  
 


④单点增减(add) + 立方体求和(query) 

⑤立方体增减(update) + 单点求值(sum) 

 
   [cpp]  
   view plain 
    copy 
   
 
   
 
    print 
   ? 
   
 
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. }  
 


⑥立方体增减(update) + 立方体求和(query)///随便写写……复杂度较高 

 
   [cpp]  
   view plain 
    copy 
   
 
   
 
    print 
   ? 
   
 
1. template<typename X>  
2. class tree_array_Cube{  
3. struct tree_array_single{  
4.         X arr[MAXN][MAXN][MAXN];  
5. 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. 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. 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. };  
 


16、树状数组—区间最大值 

 
   [cpp]  
   view plain 
    copy 
   
 
   
 
    print 
   ? 
   
 
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. }