首先二维树状数组肯定开不下
仿照二维树状数组的做法,如果有差分数组$d[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1]$,那么就有:
$$sum[x][y]=sumlimits_{i=1}^{x}{sumlimits_{j=1}^{y}{sumlimits_{k=1}^{i}{sumlimits_{l=1}^{j}{d[k][l]}}}}$$
$$=sumlimits_{i=1}^{x}{sumlimits_{k=1}^{i}{sumlimits_{j=1}^{y}{((y+1)d[k][j]-j*d[k][j])}}}$$
$$=sumlimits_{i=1}^{x}{sumlimits_{j=1}^{y}{(x+1)(y+1)d[i][j]-(x+1)*j*d[i][j]-(y+1)*i*d[i][j]+i*j*d[i][j]}}$$
所以把询问拆成四个(前缀和)、修改拆成四个(差分))
已经按时间排好序,然后把x作为第二维来cdq,开d,i*d,j*d,i*j*d四个树状数组统计答案就可以了
上帝造题的七分钟也可以这样做,不过常数太大要吸氧
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 using namespace std; 5 typedef long long ll; 6 const int maxn=1e4+10,maxm=3e4+10; 7 8 inline ll rd(){ 9 ll x=0;char c=getchar();int neg=1; 10 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 11 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 12 return x*neg; 13 } 14 15 struct Node{ 16 int t,x,y,o;ll v; 17 Node(int a=0,int b=0,int c=0,int d=0,int e=0){ 18 t=a,x=b,y=c,v=d,o=e; 19 }//o==1查 o==0改 20 }op[maxm*4],tmp[maxm*4]; 21 ll dd[maxn],id[maxn],jd[maxn],ijd[maxn]; 22 ll ans[maxm]; 23 int N,M; 24 bool isask[maxm]; 25 26 inline int lowbit(int x){return x&(-x);} 27 inline void add(ll *t,int x,ll y){ 28 for(;x<=N;x+=lowbit(x)) t[x]+=y; 29 } 30 inline ll query(ll *t,int x){ 31 ll re=0;for(;x;x-=lowbit(x)) re+=t[x];return re; 32 } 33 34 void cdq(int l,int r){ 35 if(l==r) return; 36 int m=l+r>>1; 37 cdq(l,m);cdq(m+1,r); 38 int p=l,q=m+1,n=0; 39 for(;q<=r;q++){ 40 for(;p<=m&&op[p].x<=op[q].x;p++){ 41 tmp[++n]=op[p]; 42 if(op[p].o!=0) continue; 43 add(dd,op[p].y,op[p].v); 44 add(id,op[p].y,op[p].v*op[p].x); 45 add(jd,op[p].y,op[p].v*op[p].y); 46 add(ijd,op[p].y,op[p].v*op[p].x*op[p].y); 47 } 48 tmp[++n]=op[q]; 49 if(op[q].o!=1) continue; 50 ll re=query(dd,op[q].y)*(op[q].x+1)*(op[q].y+1); 51 re-=query(id,op[q].y)*(op[q].y+1); 52 re-=query(jd,op[q].y)*(op[q].x+1); 53 re+=query(ijd,op[q].y); 54 ans[op[q].t]+=re*op[q].v; 55 }for(;p<=m;p++) tmp[++n]=op[p]; 56 for(int p=l;p<=m&&op[p].x<=op[r].x;p++){ 57 if(op[p].o!=0) continue; 58 add(dd,op[p].y,-op[p].v); 59 add(id,op[p].y,-op[p].v*op[p].x); 60 add(jd,op[p].y,-op[p].v*op[p].y); 61 add(ijd,op[p].y,-op[p].v*op[p].x*op[p].y); 62 } 63 memcpy(op+l,tmp+1,sizeof(Node)*n); 64 } 65 66 int main(){ 67 //freopen("","r",stdin); 68 int i,j; 69 N=rd(),M=rd(); 70 for(i=1,j=0;i<=M;i++){ 71 int a=rd(),x1=rd(),y1=rd(),x2=rd(),y2=rd(); 72 if(!a){ 73 op[++j]=Node(i,x2,y2,1,1); 74 if(x1>1&&y1>1) op[++j]=Node(i,x1-1,y1-1,1,1); 75 if(x1>1) op[++j]=Node(i,x1-1,y2,-1,1); 76 if(y1>1) op[++j]=Node(i,x2,y1-1,-1,1); 77 isask[i]=1; 78 }else{ 79 op[++j]=Node(i,x1,y1,a,0); 80 if(x2<N&&y2<N) op[++j]=Node(i,x2+1,y2+1,a,0); 81 if(y2<N) op[++j]=Node(i,x1,y2+1,-a,0); 82 if(x2<N) op[++j]=Node(i,x2+1,y1,-a,0); 83 } 84 } 85 cdq(1,j); 86 for(i=1;i<=M;i++){ 87 if(isask[i]) printf("%lld ",ans[i]); 88 } 89 return 0; 90 }