【模板】树状数组
一.一维树状数组
1.支持单点修改(加减),区间查询。
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,m,x,y,a[500001],Tree[500001]; 4 int lowbit(int x) 5 { 6 return x&-x; 7 } 8 void Add(int k,int x) 9 { 10 while(k<=n) 11 { 12 Tree[k]+=x; 13 k+=lowbit(k); 14 } 15 } 16 int Ask(int k) 17 { 18 int res=0; 19 while(k) 20 { 21 res+=Tree[k]; 22 k-=lowbit(k); 23 } 24 return res; 25 } 26 int main() 27 { 28 scanf("%d%d",&n,&m); 29 for(int i=1;i<=n;i++) 30 { 31 scanf("%d",&a[i]); 32 Add(i,a[i]); 33 } 34 for(int i=1;i<=m;i++) 35 { 36 scanf("%d",&x); 37 if(x==1) 38 { 39 scanf("%d%d",&x,&y); 40 Add(x,y); 41 } 42 else if(x==2) 43 { 44 scanf("%d%d",&x,&y); 45 printf("%d\n",Ask(y)-Ask(x-1)); 46 } 47 } 48 return 0; 49 }
2.支持区间修改(加减),单点查询。
对差分数组建立树状数组,修改时在l位置加w,r+1位置减w。
#include<bits/stdc++.h> using namespace std; int n,m,x,y,z,a[500001],Tree[500001]; int lowbit(int x) { return x&-x; } void Add(int k,int x) { while(k<=n) { Tree[k]+=x; k+=lowbit(k); } } int Ask(int k) { int res=0; while(k) { res+=Tree[k]; k-=lowbit(k); } return res; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); Add(i,a[i]-a[i-1]); } for(int i=1;i<=m;i++) { scanf("%d",&x); if(x==1) { scanf("%d%d%d",&x,&y,&z); Add(x,z); Add(y+1,-z); } else if(x==2) { scanf("%d",&x); printf("%d\n",Ask(x)); } } return 0; }
3.支持区间修改(加减),区间查询。
两个树状数组差分。
#include<bits/stdc++.h> using namespace std; int n,m,x,y,z; long long a[500001],Tree1[500001],Tree2[500001]; int lowbit(int x) { return x&-x; } void Add(int k,int x) { int i=k; while(i<=n) { Tree1[i]+=x; Tree2[i]+=x*(k-1); i+=lowbit(i); } } long long Ask(int k) { long long res=0; int i=k; while(i) { res+=k*Tree1[i]-Tree2[i]; i-=lowbit(i); } return res; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); Add(i,a[i]-a[i-1]); } for(int i=1;i<=m;i++) { scanf("%d",&x); if(x==1) { scanf("%d%d%d",&x,&y,&z); Add(x,z); Add(y+1,-z); } else if(x==2) { scanf("%d%d",&x,&y); printf("%lld\n",Ask(y)-Ask(x-1)); } } return 0; }
二.二维树状数组
查询子矩阵元素和。
#include<bits/stdc++.h> using namespace std; int n,m,x,y,s,x1,yy,x2,y2; long long Tree[1025][1025],z; int lowbit(int x) { return x&-x; } void Add(int x,int y,long long k) { int yy=y; while(x<=n) { while(y<=n) { Tree[x][y]+=k; y+=lowbit(y); } y=yy; x+=lowbit(x); } } long long Ask(int x,int y) { int yy=y; long long res=0; while(x>0) { while(y>0) { res+=Tree[x][y]; y-=lowbit(y); } y=yy; x-=lowbit(x); } return res; } int main() { scanf("%d",&n); while(1) { scanf("%d",&s); if(s==3) return 0; if(s==1) { scanf("%d%d%lld",&x,&y,&z); { Add(x+1,y+1,z); } } if(s==2) { scanf("%d%d%d%d",&x1,&yy,&x2,&y2); printf("%lld\n",Ask(x2+1,y2+1)-Ask(x1,y2+1)-Ask(x2+1,yy)+Ask(x1,yy)); } } return 0; }