首先二维树状数组肯定开不下
仿照二维树状数组的做法,如果有差分数组$d[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1]$,那么就有:
$$sum[x][y]=\sum\limits_{i=1}^{x}{\sum\limits_{j=1}^{y}{\sum\limits_{k=1}^{i}{\sum\limits_{l=1}^{j}{d[k][l]}}}}$$
$$=\sum\limits_{i=1}^{x}{\sum\limits_{k=1}^{i}{\sum\limits_{j=1}^{y}{((y+1)d[k][j]-j*d[k][j])}}}$$
$$=\sum\limits_{i=1}^{x}{\sum\limits_{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四个树状数组统计答案就可以了
上帝造题的七分钟也可以这样做,不过常数太大要吸氧
#include<bits/stdc++.h>
#define pa pair<int,int>
#define CLR(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=1e4+,maxm=3e4+; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} struct Node{
int t,x,y,o;ll v;
Node(int a=,int b=,int c=,int d=,int e=){
t=a,x=b,y=c,v=d,o=e;
}//o==1查 o==0改
}op[maxm*],tmp[maxm*];
ll dd[maxn],id[maxn],jd[maxn],ijd[maxn];
ll ans[maxm];
int N,M;
bool isask[maxm]; inline int lowbit(int x){return x&(-x);}
inline void add(ll *t,int x,ll y){
for(;x<=N;x+=lowbit(x)) t[x]+=y;
}
inline ll query(ll *t,int x){
ll re=;for(;x;x-=lowbit(x)) re+=t[x];return re;
} void cdq(int l,int r){
if(l==r) return;
int m=l+r>>;
cdq(l,m);cdq(m+,r);
int p=l,q=m+,n=;
for(;q<=r;q++){
for(;p<=m&&op[p].x<=op[q].x;p++){
tmp[++n]=op[p];
if(op[p].o!=) continue;
add(dd,op[p].y,op[p].v);
add(id,op[p].y,op[p].v*op[p].x);
add(jd,op[p].y,op[p].v*op[p].y);
add(ijd,op[p].y,op[p].v*op[p].x*op[p].y);
}
tmp[++n]=op[q];
if(op[q].o!=) continue;
ll re=query(dd,op[q].y)*(op[q].x+)*(op[q].y+);
re-=query(id,op[q].y)*(op[q].y+);
re-=query(jd,op[q].y)*(op[q].x+);
re+=query(ijd,op[q].y);
ans[op[q].t]+=re*op[q].v;
}for(;p<=m;p++) tmp[++n]=op[p];
for(int p=l;p<=m&&op[p].x<=op[r].x;p++){
if(op[p].o!=) continue;
add(dd,op[p].y,-op[p].v);
add(id,op[p].y,-op[p].v*op[p].x);
add(jd,op[p].y,-op[p].v*op[p].y);
add(ijd,op[p].y,-op[p].v*op[p].x*op[p].y);
}
memcpy(op+l,tmp+,sizeof(Node)*n);
} int main(){
//freopen("","r",stdin);
int i,j;
N=rd(),M=rd();
for(i=,j=;i<=M;i++){
int a=rd(),x1=rd(),y1=rd(),x2=rd(),y2=rd();
if(!a){
op[++j]=Node(i,x2,y2,,);
if(x1>&&y1>) op[++j]=Node(i,x1-,y1-,,);
if(x1>) op[++j]=Node(i,x1-,y2,-,);
if(y1>) op[++j]=Node(i,x2,y1-,-,);
isask[i]=;
}else{
op[++j]=Node(i,x1,y1,a,);
if(x2<N&&y2<N) op[++j]=Node(i,x2+,y2+,a,);
if(y2<N) op[++j]=Node(i,x1,y2+,-a,);
if(x2<N) op[++j]=Node(i,x2+,y1,-a,);
}
}
cdq(,j);
for(i=;i<=M;i++){
if(isask[i]) printf("%lld\n",ans[i]);
}
return ;
}