题解:
和二维的比起来差不多。
但是这是四维偏序。
所以搞一下CDQ套CDQ。
CDQ是维度a已经有序,按维度b排序,然后将维度c存入一维数据结构。
所以我们在第一层CDQ中分治处理,将合法的前一半打标记。
然后进入第二层CDQ,处理打标记的点对没打标记的点的影响。
可以说是将两维压成一维。
想法仍然是容斥。
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 50050 #define ll long long inline int rd() { int f=1,c=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();} return f*c; } struct node { int x,y,z,t,w,k,id; int typ; node(){} node(int x,int y,int t,int w,int k,int i):x(x),y(y),t(t),w(w),k(k),id(i){} }p[N<<3],tmp[N<<3],sec[N<<3]; bool cmpx(node a,node b) { return a.x<b.x; } bool cmpid(node a,node b) { return a.id<b.id; } int cnt; struct PR { int x,id; PR(){} PR(int x,int i):x(x),id(i){} }Z[N<<3]; bool cmp(PR a,PR b) { return a.x<b.x; } int T,Q,typ,tim; int kkk[N<<1],ct; ll ans[N]; struct BIT { ll v[N<<3]; void up(int x,ll d) { if(!x)return ; while(x<(N<<3)) v[x]+=d,x+=(x&-x); } ll down(int x) { if(!x)return 0; ll ret = 0ll; while(x) ret+=v[x],x-=(x&-x); return ret; } }tr; void init() { cnt=ct=0; tim=1; } void ap(int x,int y,int z,int t,int w,int k) { cnt++; p[cnt] = node(x,y,t,w,k,cnt); Z[cnt] = PR(z,cnt); } void Sort(int l,int r) { int mid = (l+r)>>1; int i=l,j=mid+1,k=l; while(i<=mid&&j<=r) { while(i<=mid&&tmp[i].y<=tmp[j].y) { sec[k]=tmp[i]; i++,k++; } while(j<=r&&tmp[i].y>tmp[j].y) { sec[k]=tmp[j]; j++,k++; } } while(i<=mid) { sec[k]=tmp[i]; i++,k++; } while(j<=r) { sec[k]=tmp[j]; j++,k++; } for(i=l;i<=r;i++) tmp[i]=sec[i]; } void cdq2(int l,int r) { if(l==r)return ; int mid = (l+r)>>1; cdq2(l,mid);cdq2(mid+1,r); Sort(l,mid);Sort(mid+1,r); int i,j; for(i=l,j=mid+1;j<=r;j++) { while(i<=mid&&tmp[i].y<=tmp[j].y) { if(tmp[i].typ&&tmp[i].w)tr.up(tmp[i].z,tmp[i].w); i++; } if(kkk[tmp[j].t]&&!tmp[j].typ)ans[kkk[tmp[j].t]]+=1ll*tmp[j].k*tr.down(tmp[j].z); } for(i=i-1;i>=l;i--) if(tmp[i].typ&&tmp[i].w)tr.up(tmp[i].z,-tmp[i].w); } void cdq1(int l,int r) { if(l==r)return ; int mid = (l+r)>>1; cdq1(l,mid),cdq1(mid+1,r); sort(p+l,p+mid+1,cmpx); sort(p+mid+1,p+r+1,cmpx); int i=l,j=mid+1,k=l; while(i<=mid&&j<=r) { while(i<=mid&&p[i].x<=p[j].x) { tmp[k]=p[i],tmp[k].typ=1; i++,k++; } while(j<=r&&p[i].x>p[j].x) { tmp[k]=p[j],tmp[k].typ=0; j++,k++; } } while(i<=mid) { tmp[k]=p[i],tmp[k].typ=1; i++,k++; } while(j<=r) { tmp[k]=p[j],tmp[k].typ=0; j++,k++; } cdq2(l,r); } int main() { T=rd(); while(T--) { init(); Q = rd(); for(int ax,ay,az,bx,by,bz,i=1;i<=Q;i++) { typ=rd(); if(typ==1) { ax=rd(),ay=rd(),az=rd(); ap(ax,ay,az,tim,1,0); }else { ax=rd(),ay=rd(),az=rd(),bx=rd(),by=rd(),bz=rd(); tim++,ct++; kkk[tim]=ct; ax--,ay--,az--; ap(ax,ay,az,tim,0,-1); ap(ax,ay,bz,tim,0,1); ap(ax,by,az,tim,0,1); ap(ax,by,bz,tim,0,-1); ap(bx,ay,az,tim,0,1); ap(bx,ay,bz,tim,0,-1); ap(bx,by,az,tim,0,-1); ap(bx,by,bz,tim,0,1); tim++; } } sort(Z+1,Z+1+cnt,cmp); for(int las=-1,k=0,i=1;i<=cnt;i++) { if(las!=Z[i].x) { las = Z[i].x; k++; } p[Z[i].id].z = k; } cdq1(1,cnt); for(int i=1;i<=ct;i++) printf("%I64d ",ans[i]); for(int i=1;i<=ct;i++) ans[i]=0; } return 0; }