很裸的一道CDQ分治题,这题对于每个询问处理为二维前缀的形式,那么就可以分裂成四个查询,然后以时间、x、y三维做CDQ分治,大概怎么搞都可以吧。
#include #include #include #include #include #include #include #include #include #define ll long long #define MOD 1000000007 #define N 210000 #define M 10010000 #define RG register using namespace std; inline ll read(){ RG ll x=0,o=1; RG char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-') ch=getchar(); if(ch=='-') o=-1,ch=getchar(); while(ch>='0'&&ch<='9') x=((x<<3)+(x<<1))+ch-'0',ch=getchar(); return x*o; } struct mona { int t,op,x,y; ll val,id,opt; } s[N],q[N]; inline bool cmp(mona x,mona y) { return x.t>1; CDQ(l,mid),CDQ(mid+1,r); RG int i,j,now; for(i=l,j=mid+1,now=l-1;i<=mid,j<=r;) if(s[i].xs[j].x&&j<=r) q[++now]=s[j++]; else if(s[i].op==1&&i<=mid) q[++now]=s[i++]; else q[++now]=s[j++]; while(i<=mid) q[++now]=s[i++]; while(j<=r) q[++now]=s[j++]; for(i=l;i<=r;++i){ s[i]=q[i]; if(s[i].op==1&&s[i].t<=mid) Update(s[i].y,s[i].val); if(s[i].op==2&&s[i].t>mid) s[i].val+=Query(s[i].y); } for(i=l;i<=r;++i) if(s[i].op==1&&s[i].t<=mid) Update(s[i].y,-s[i].val); } int main(){ read(),n=read(); RG int op,t=0; while((op=read())!=3) if(op==1) s[++t]=(mona) { t,op,read(),read(),read() }; else{ int x=read(),y=read(),tx=read(),ty=read(); ++top; s[++t]=(mona) { t,op,x-1,y-1,0,top,+1 },s[++t]=(mona) { t,op,tx,ty,0,top,+1 }; s[++t]=(mona) { t,op,x-1,ty,0,top,-1 },s[++t]=(mona) { t,op,tx,y-1,0,top,-1 }; } CDQ(1,t); for(RG int i=1;i<=t;++i) if(s[i].op==2) ans[s[i].id]+=s[i].opt*s[i].val; for(RG int i=1;i<=top;++i) printf("%lld\n",ans[i]); }