C94 二维树状数组+差分 P4514 上帝造题的七分钟
视频链接:C94 二维树状数组+差分 P4514 上帝造题的七分钟_哔哩哔哩_bilibili
// 二维树状数组+差分 区修+区查 O(q*logn*logn) #include <cstdio> using namespace std; #define lowb(x) x&-x int n,m,a,b,c,d,v; char op[2]; struct Tree{ //二维树状数组 int s[2050][2050]; void change(int x,int y,int v){ //向后修 for(int i=x;i<=n;i+=lowb(i)) for(int j=y;j<=m;j+=lowb(j)) s[i][j]+=v; } int query(int x,int y){ //向前查 int t=0; for(int i=x;i;i-=lowb(i)) for(int j=y;j;j-=lowb(j)) t+=s[i][j]; return t; } }A,B,C,D; //维护 d,d*i,d*j,d*i*j void add(int x,int y,int v){ //点加 A.change(x,y,v); B.change(x,y,v*x); C.change(x,y,v*y); D.change(x,y,v*x*y); } int sum(int x,int y){ //前缀和 return A.query(x,y)*(x*y+x+y+1) -B.query(x,y)*(y+1) -C.query(x,y)*(x+1) +D.query(x,y); } int main(){ scanf("X%d%d",&n,&m); while(~scanf("%s",&op)){ scanf("%d%d%d%d",&a,&b,&c,&d); if(op[0]=='L'){ //区修变差分 scanf("%d",&v); add(a,b,v); add(a,d+1,-v); add(c+1,b,-v); add(c+1,d+1,v); } else //区间和 printf("%d\n",sum(c,d) -sum(a-1,d)-sum(c,b-1) +sum(a-1,b-1)); } }
// 二维树状数组+差分 区修+区查 O(q*logn*logn) #include <cstdio> using namespace std; #define lowb(x) x&-x int n,m,a,b,c,d,v; char op[2]; int s[2050][2050][4]; void change(int x,int y,int k,int v){ //向后修 for(int i=x;i<=n;i+=lowb(i)) for(int j=y;j<=m;j+=lowb(j)) s[i][j][k]+=v; } int query(int x,int y,int k){ //向前查 int t=0; for(int i=x;i;i-=lowb(i)) for(int j=y;j;j-=lowb(j)) t+=s[i][j][k]; return t; } void add(int x,int y,int v){ //点加 change(x,y,0,v); change(x,y,1,v*x); change(x,y,2,v*y); change(x,y,3,v*x*y); } int sum(int x,int y){ //前缀和 return query(x,y,0)*(x*y+x+y+1) -query(x,y,1)*(y+1) -query(x,y,2)*(x+1) +query(x,y,3); } int main(){ scanf("X%d%d",&n,&m); while(~scanf("%s",&op)){ scanf("%d%d%d%d",&a,&b,&c,&d); if(op[0]=='L'){ //区修变差分 scanf("%d",&v); add(a,b,v); add(a,d+1,-v); add(c+1,b,-v); add(c+1,d+1,v); } else //区间和 printf("%d\n",sum(c,d) -sum(a-1,d)-sum(c,b-1) +sum(a-1,b-1)); } }