$CDQ$分治。
考虑此时在区间$[l,r]$中,要计算$[l,mid]$中的操作对$[mid+1,r]$中的询问的影响。
计算时,排序加上树状数组即可。
然后再递归处理$[l,mid]$和$[mid+1,r]$。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int MAX=2000005; struct data { int opt,x,y,y1,w,num; data(int a=0,int b=0,int c=0,int d=0,int e=0,int f=0) {opt=a,x=b,y=c,y1=d,w=e,num=f;} }s[200005],g[200005]; bool cmp(data u,data v) {return (u.x==v.x)?(u.opt<v.opt):(u.x<v.x);} int ans[10005],val[2000100]; int lowbit(int x) {return x&(-x);} void add(int x,int y) {for(;x<=MAX;x+=lowbit(x)) val[x]+=y;} int ask(int x) {int ans=0;for(;x;x-=lowbit(x))ans+=val[x];return ans;} void cln(int x) {for(;x<=MAX;x+=lowbit(x)) val[x]=0;} int Get(int l,int r) {return ask(r)-ask(l-1);} void Sol(int l,int mid,int r) { int k=0; for(int i=l;i<=mid;i++) if(s[i].opt==1) g[++k]=s[i]; for(int i=mid+1;i<=r;i++) if(s[i].opt!=1) g[++k]=s[i]; sort(g+1,g+k+1,cmp); for(int i=1;i<=k;i++) { if(g[i].opt==1) add(g[i].y,g[i].w); if(g[i].opt==2) ans[g[i].num]-=Get(g[i].y,g[i].y1); if(g[i].opt==3) ans[g[i].num]+=Get(g[i].y,g[i].y1); } for(int i=1;i<=k;i++) if(g[i].opt==1) cln(g[i].y); } void CDQ(int l,int r) { if(l==r) return; int mid=(l+r)>>1; CDQ(l,mid),CDQ(mid+1,r); Sol(l,mid,r); } int main() { int n=0,cnt=0,tot=0; scanf("%d%d",&n,&n); for(;;) { int opt=0; scanf("%d",&opt); if(opt==3) break; if(opt==1) { s[++cnt].opt=1; scanf("%d%d%d",&s[cnt].x,&s[cnt].y,&s[cnt].w); s[cnt].x++,s[cnt].y++; } if(opt==2) { tot++; s[++cnt].opt=2,s[cnt].num=tot; scanf("%d%d",&s[cnt].x,&s[cnt].y),s[cnt].y++; s[++cnt].opt=3,s[cnt].num=tot; scanf("%d%d",&s[cnt].x,&s[cnt].y1),s[cnt].x++,s[cnt].y1++; s[cnt].y=s[cnt-1].y; s[cnt-1].y1=s[cnt].y1; } } CDQ(1,cnt); for(int i=1;i<=tot;i++) printf("%d ",ans[i]); return 0; }