[CDQ分治][Treap][树状数组]Theresa与数据结构
分析
这题是个四维偏序问题。
时间那维我们用CDQ分治解决
x我们可以排序离散化
y用树状数组,z用Treap(没敢用Splay常数太大233)
那么这题是一个CDQ分治套树套树
(写LowerBound气死了,忘记在上界加个1)
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #define rep(i,a,b) for (i=a;i<=b;i++) #define lowbit(x) x&-x const int N=100005; using namespace std; struct Node { int l,r,key,mak,dat,sum; }t[50*N]; int tcnt; struct Point { int x,y,z; }stk[N]; struct Query { Point p; int r,t,id; }q[N],a[2*N]; int qcnt; int rt[N]; int sy,sq,sh,n,m,top; int ans[N],y[N]; //Treap void Update(int x) { t[x].sum=t[x].dat+t[t[x].l].sum+t[t[x].r].sum; } void Left_Rotate(int &x) { int s=t[x].r; t[x].r=t[s].l;t[s].l=x; Update(x);Update(s); x=s; } void Right_Rotate(int &x) { int s=t[x].l; t[x].l=t[s].r;t[s].r=x; Update(x);Update(s); x=s; } void Insert(int &x,int mak,int dat) { if (!x) { x=++tcnt;t[x].l=t[x].r=0;t[x].mak=mak;t[x].sum=t[x].dat=dat;t[x].key=rand(); return; } if (mak<t[x].mak) { Insert(t[x].l,mak,dat); if (t[t[x].l].key>t[x].key) Right_Rotate(x); } else { Insert(t[x].r,mak,dat); if (t[t[x].r].key>t[x].key) Left_Rotate(x); } Update(x); } int Get_Suk(int x,int mak) { if (!x) return 0; if (mak<t[x].mak) return Get_Suk(t[x].l,mak); return Get_Suk(t[x].r,mak)+t[x].dat+t[t[x].l].sum; } //Treearray void Add(int x,int z,int dat) { for (int i=x;i<=sy+1;i+=lowbit(i)) Insert(rt[i],z,dat); } int Get_Sum(int x,int z,int r) { int ans=0; for (int i=x;i;i-=lowbit(i)) ans+=Get_Suk(rt[i],z+r)-Get_Suk(rt[i],z-1); return ans; } void Init() { int i; char s[20]; scanf("%d",&n); rep(i,1,n) { sq++; scanf("%d%d%d",&q[sq].p.x,&q[sq].p.y,&q[sq].p.z); q[sq].id=sq;q[sq].t=1; } scanf("%d",&m); rep(i,1,m) { scanf("%s",&s); if (s[0]=='A') { sq++; scanf("%d%d%d",&q[sq].p.x,&q[sq].p.y,&q[sq].p.z); q[sq].id=sq;q[sq].t=1; stk[++top]=q[sq].p; } if (s[0]=='C') { sq++; q[sq].p=stk[top--]; q[sq].id=sq;q[sq].t=-1; } if (s[0]=='Q') { sq++; scanf("%d%d%d%d",&q[sq].p.x,&q[sq].p.y,&q[sq].p.z,&q[sq].r); q[sq].id=sq;q[sq].t=0; } } } bool Cmp(Query a,Query b) { return a.p.x<b.p.x||a.p.x==b.p.x&&a.t<b.t; } int Lower_Bound(int l,int r,int x) { if (x<y[1]) return 1; while (l<r) { int mid=l+r+1>>1; if (y[mid]>x) r=mid-1; else l=mid; } return l+1; } void Fix() { int i; sort(a+1,a+sh+1,Cmp); sy=0; rep(i,1,sh) if (a[i].t<2) y[++sy]=a[i].p.y; sort(y+1,y+sy+1); sy=unique(y+1,y+sy+1)-(y+1); rep(i,1,sy+1) rt[i]=0;tcnt=0; rep(i,1,sh) { if (a[i].t<2) Add(Lower_Bound(1,sy,a[i].p.y),a[i].p.z,a[i].t); else { int l=Lower_Bound(1,sy,a[i].p.y-1),r=Lower_Bound(1,sy,a[i].p.y+a[i].r); if (l==r) continue; ans[a[i].id]+=(Get_Sum(r,a[i].p.z,a[i].r)-Get_Sum(l,a[i].p.z,a[i].r))*(a[i].t-3); } } } bool In(Point a,Point b,int r) { return a.x>=b.x&&a.y>=b.y&&a.z>=b.z&&a.x<=b.x+r&&a.y<=b.y+r&&a.z<=b.z+r; } void Work(int l,int r) { int so=0,sa=0,i,j; rep(i,l,r) if (!q[i].t) sa++; else so++; if (!sa||!so) return; if (r-l+1<=400) { rep(i,l,r-1) rep(j,i+1,r) if (!q[j].t&&In(q[i].p,q[j].p,q[j].r)) ans[q[j].id]+=q[i].t; return; } int mid=l+r>>1; if (l==1&&r==sq) mid=n; Work(l,mid); Work(mid+1,r); sh=0; rep(i,l,mid) if (q[i].t!=0) a[++sh]=q[i]; int hs=sh; rep(i,mid+1,r) if (!q[i].t) { a[++sh]=q[i];a[sh].p.x--;a[sh].t=2; a[++sh]=q[i];a[sh].p.x+=q[i].r;a[sh].t=4; } if (hs&&sh>hs) Fix(); } void Print() { int i; rep(i,1,sq) if (!q[i].t) printf("%d\n",ans[q[i].id]); } int main() { Init(); Work(1,sq); Print(); }
在日渐沉没的世界里,我发现了你。