题目链接
题目大意:
总体思路:
二维差分数组d[i][j]等于a[i][j]和a[i-1][j]+a[i][j-1]-a[i-1][j-1]的差=a[i][j]-(a[i-1][j]+a[i][j-1])+a[i-1][j-1](可以根据二维前缀和来理解)。
1、在二维矩阵进行修改操作,就是在二维差分数组上进行操作:
d[x1][y1] += c;
d[x1][y2+1] -=c;
d[x2+1][y1] -=c;
d[x2+1][y2+1] += c;
2、在二维矩阵进行查询操作
s[i][j]为二维差分数组的前缀和的前缀和(也就是矩阵的前缀和),求(x1,y1)和(x2,y2)的矩阵和=s[x2][y2]-s[x2][y1-1]-
s[x1-1][y2]+s[x1-1][y1-1]
求具体的s[x][y]=
于是我们就需要维护四个树状数组d[i][j],d[i][j]∗i,d[i][j]∗j,d[i][j]∗i∗j,从而实现区间查询。
推荐博客
下面代码就是二维树状数组的板子啦
#include<iostream> using namespace std; typedef long long ll; int n,m; char ch; int x,x1,y1,x2,y2; int tr[4][2050][2050]; int lowbit(int i){ return i&-i; } void vadd(int f,int x,int y,int d){ for(int i=x;i<=n;){ for(int j=y;j<=m;){ tr[f][i][j]+=d; j+=lowbit(j); } i+=lowbit(i); } return ; } void add(int x,int y,int d){ vadd(0,x,y,d); vadd(1,x,y,d*x); vadd(2,x,y,d*y); vadd(3,x,y,d*x*y); return ; } int vquery(int f,int x,int y){ int s=0; for(int i=x;i>0;){ for(int j=y;j>0;){ s+=tr[f][i][j]; j-=lowbit(j); } i-=lowbit(i); } return s; } int query(int x,int y){ return vquery(0,x,y)*(x*y+x+y+1)-vquery(1,x,y)*(y+1)-vquery(2,x,y)*(x+1)+vquery(3,x,y); } int main(){ scanf("X %d %d",&n,&m); while(~scanf(" %c",&ch)){ scanf(" %d %d %d %d",&x1,&y1,&x2,&y2); if(ch=='L'){ scanf(" %d",&x); add(x1,y1,x); add(x2+1,y1,-x); add(x1,y2+1,-x); add(x2+1,y2+1,x); } else{ int ans=query(x2,y2)-query(x2,y1-1)-query(x1-1,y2)+query(x1-1,y1-1); printf("%d\n",ans); } } return 0; }