二维树状数组涉及到两种基本操作,修改矩阵中的一个点,查询子矩阵的和。
首先是修改点:
void update(int x,int y,int z) { for(int i=x;i<=n;i+=lowbit(i)) for(int j=y;j<=m;j+=lowbit(j)) c[i][j]+=z; }
然后是查询前缀和:
int get_sum(int x,int y) { int ret=0; for(int i=x;i>=1;i-=lowbit(i)) for(int j=y;j>=1;j-=lowbit(j)) ret+=c[i][j]; return ret; }
那么由容斥原理:
inline int query(int x1,int y1,int x2,int y2){ return get_sum(x2,y2)-get_sum(x1-1,y2)-get_sum(x2,y1-1)+get_sum(x1-1,y1-1); }
区间修改就麻烦一点:
方法1:
#include<iostream> using namespace std; const int maxn=1005; const int maxm=1005; int n,m; int q; int a[maxn][maxm]; int c[maxn][maxm]; int lowbit(int x) { return x&(-x); } void update(int x,int y,int z) { for(int i=x;i<=n;i+=lowbit(i)) for(int j=y;j<=m;j+=lowbit(j)) c[i][j]+=z; } int sum(int x,int y) { int ret=0; for(int i=x;i>=1;i-=lowbit(i)) for(int j=y;j>=1;j-=lowbit(j)) ret+=c[i][j]; return ret; } int main() { cin>>n>>m; cin>>q; while(q--) { int x; cin>>x; if(x==1) { int x1,y1,x2,y2,w; cin>>x1>>y1>>x2>>y2>>w; update(x1,y1,w); update(x2+1,y2+1,w); update(x2+1,y1,-w); update(x1,y2+1,-w); } if(x==2) { int x,y; cin>>x>>y; cout<<sum(x,y)<<endl; } } return 0; }
方法2:
#include<iostream> using namespace std; const int maxn=1005; const int maxm=1005; int n,m; int q; int a[maxn][maxm]; int c1[maxn][maxm]; int c2[maxn][maxm]; int c3[maxn][maxm]; int c4[maxn][maxm]; int lowbit(int x) { return x&(-x); } void update(int c[][maxm],int x,int y,int z) { for(int i=x;i<=n;i+=lowbit(i)) for(int j=y;j<=m;j+=lowbit(j)) c[i][j]+=z; } int sum(int c[][maxm],int x,int y) { int ret=0; for(int i=x;i>=1;i-=lowbit(i)) for(int j=y;j>=1;j-=lowbit(j)) ret+=c[i][j]; return ret; } int get(int x,int y) { return sum(c1,x,y)*(x+1)*(y+1)-sum(c2,x,y)*(y+1)-(x+1)*sum(c3,x,y)+sum(c4,x,y); } int main() { cin>>n>>m; cin>>q; while(q--) { int x; cin>>x; if(x==1) { int x1,y1,x2,y2,w; cin>>x1>>y1>>x2>>y2>>w; update(c1,x1,y1,w),update(c1,x1,y2+1,-w); update(c1,x2+1,y1,-w),update(c1,x2+1,y2+1,w); update(c2,x1,y1,w*x1),update(c2,x2+1,y1,-w*(x2+1)); update(c2,x1,y2+1,-w*x1),update(c2,x2+1,y2+1,w*(x2+1)); update(c3,x1,y1,w*y1),update(c3,x2+1,y1,-w*y1); update(c3,x1,y2+1,-w*(y2+1)),update(c3,x2+1,y2+1,w*(y2+1)); update(c4,x1,y1,w*x1*y1),update(c4,x2+1,y1,-w*(x2+1)*y1); update(c4,x1,y2+1,-w*x1*(y2+1)),update(c4,x2+1,y2+1,w*(x2+1)*(y2+1)); } if(x==2) { int x1,y1,x2,y2; cin>>x1>>y1>>x2>>y2; cout<<get(x2,y2)-get(x2,y1-1)-get(x1-1,y2)+get(x1-1,y1-1)<<endl; } } return 0; }