关键在于吧询问用容斥拆成4个点
/************************************************************** Problem: 1176 User: lxy8584099 Language: C++ Result: Accepted Time:5432 ms Memory:18796 kb ****************************************************************/ /* 三维偏序 时间戳算一维 先把x当做第一维排序 时间当做第二维 y当做第三维 那么时间 也就是第二维就要用分治了 第三维树状数组 修改一个点 查询拆成4个点 ++-- 容斥 4个点时间戳也要不一样 */ #include<cstdio> #include<algorithm> #define lowbit(x) ((x)&(-x)) #define mid ((l+r)>>1) using namespace std; const int N=200005; struct pp { int x,y,id,dfn,val,opt; pp() { x=y=id=dfn=val=opt=0; } } a[N],b[N]; // id表示示是第几个询问 // val表示增加的值或者++-- opt表示是否是询问操作 bool cmp(pp a,pp b) { if(a.x!=b.x) return a.x<b.x; return a.id<b.id; } int s[N*10],ans[N]; int n,tot,as,res; void add(int x,int c) {while(x<=n) s[x]+=c,x+=lowbit(x);} int find(int x) {res=0;while(x) res+=s[x],x-=lowbit(x);return res;} void CDQ(int l,int r) { if(l>=r) return ; CDQ(l,mid),CDQ(mid+1,r); int i=l,j=mid+1,p=l; while(i<=mid&&j<=r) { if(a[i].id<a[j].id) { if(!a[i].opt) add(a[i].y,a[i].val); b[p++]=a[i++]; } else { if(a[j].opt) ans[a[j].dfn]+=find(a[j].y)*a[j].val; b[p++]=a[j++]; } } while(i<=mid) { if(!a[i].opt) add(a[i].y,a[i].val); b[p++]=a[i++]; } while(j<=r) { if(a[j].opt) ans[a[j].dfn]+=find(a[j].y)*a[j].val; b[p++]=a[j++]; } for(int i=l;i<=mid;i++) if(!a[i].opt) add(a[i].y,-a[i].val); for(int i=l;i<=r;i++) a[i]=b[i]; } int main() { scanf("%*d%d",&n); for(int op,x1,x2,y1,y2,x,y,c;;) { scanf("%d",&op); if(op==3) break; else if(op==1) { scanf("%d%d%d",&x,&y,&c); a[++tot].x=x,a[tot].y=y,a[tot].val=c,a[tot].id=tot; } else { as++; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); a[++tot].x=x1-1,a[tot].y=y1-1,a[tot].id=tot; a[tot].dfn=as,a[tot].val=1,a[tot].opt=1; a[++tot].x=x1-1,a[tot].y=y2,a[tot].id=tot; a[tot].dfn=as,a[tot].val=-1,a[tot].opt=1; a[++tot].x=x2,a[tot].y=y1-1,a[tot].id=tot; a[tot].dfn=as,a[tot].val=-1,a[tot].opt=1; a[++tot].x=x2,a[tot].y=y2,a[tot].id=tot; a[tot].dfn=as,a[tot].val=1,a[tot].opt=1; } } sort(a+1,a+tot+1,cmp); CDQ(1,tot); for(int i=1;i<=as;i++) printf("%d\n",ans[i]); return 0; }