蒟蒻的垂死挣扎
很裸的一道CDQ分治题,这题对于每个询问处理为二维前缀的形式,那么就可以分裂成四个查询,然后以时间、x、y三维做CDQ分治,大概怎么搞都可以吧。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#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<y.t; }
int n,tr[2001000],top; ll ans[11000];
inline void Update(int x,ll y){
for(RG int i=x;i<=n&&i;i+=(i&-i)) tr[i]+=y;
}
inline ll Query(int x){ RG ll ans=0;
for(RG int i=x;i;i-=(i&-i)) ans+=tr[i]; return ans;
}
inline void CDQ(int l,int r){
if(l==r) return ; int mid=(l+r)>>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].x<s[j].x&&i<=mid) q[++now]=s[i++];
else if(s[i].x>s[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]);
}