【HDU5126】 stars k-d树
题目大意:有$m$个操作,分两种:在指定三维坐标内加入一个点,询问指定空间内点的数量。
其中$m≤5*10^{4},1≤x,y,z≤10^9$
这题几乎就是裸的$k-d$树啊。我们动态维护一棵$k-d$树,对于以某个节点为根的字树中,维护该子树中点的三维范围,以及该子树中点的数量。然后直接查询即可。
PS:为了保证你的程序不会变成“优秀”的$n^{2}$做法,需要写一个类似虚树暴力重构的东西,去控制该树的平衡。
#include<bits/stdc++.h> #define M 100000 using namespace std; struct node{ int a[3],max[3],min[3],sum,l,r,d; node(){ a[0]=a[1]=a[2]=0; max[0]=max[1]=max[2]=0; min[0]=min[1]=min[2]=1234567890; sum=d=l=r=0; } node(int x,int y,int z){ a[0]=x; a[1]=y; a[2]=z; sum=l=d=r=0; max[0]=max[1]=max[2]=0; min[0]=min[1]=min[2]=1234567890; } node(int x1,int y1,int z1,int x2,int y2,int z2){ max[0]=x2; max[1]=y2; max[2]=z2; min[0]=x1; min[1]=y1; min[2]=z1; a[0]=a[1]=a[2]=sum=l=r=d=0; } }a[M]; int root=0,use=0; int id[M]={0},rebid=0,rebfa=0,now=0; void add(int &x,int fa,int d,node k){ if(!x) x=++use,a[x]=k,a[x].d=d; else{ if(k.a[d]<a[x].a[d]) add(a[x].l,x,(d+1)%3,k); else add(a[x].r,x,(d+1)%3,k); } a[x].max[0]=max(a[x].max[0],k.a[0]); a[x].min[0]=min(a[x].min[0],k.a[0]); a[x].max[1]=max(a[x].max[1],k.a[1]); a[x].min[1]=min(a[x].min[1],k.a[1]); a[x].max[2]=max(a[x].max[2],k.a[2]); a[x].min[2]=min(a[x].min[2],k.a[2]); a[x].sum++; if(max(a[a[x].l].sum,a[a[x].r].sum)>a[x].sum*0.7) rebid=x,rebfa=fa; } int D; bool cmp(int x,int y){ return a[x].a[D]<a[y].a[D]; } void bl(int x){ if(!x) return; id[++now]=x; bl(a[x].l); bl(a[x].r); a[x].max[0]=a[x].max[1]=a[x].max[2]=a[x].l=a[x].r=a[x].sum=a[x].d=0; a[x].min[0]=a[x].min[1]=a[x].min[2]=1234567890; } void rebuild(int &x,int l,int r,int d){ if(l>r) return; int mid=(l+r)>>1; D=d; nth_element(id+l,id+mid,id+r+1,cmp); x=id[mid]; rebuild(a[x].l,l,mid-1,(d+1)%3); rebuild(a[x].r,mid+1,r,(d+1)%3); for(int i=0;i<3;i++) a[x].max[i]=max(a[x].a[i],max(a[a[x].l].max[i],a[a[x].r].max[i])), a[x].min[i]=min(a[x].a[i],min(a[a[x].l].min[i],a[a[x].r].min[i])); a[x].sum=a[a[x].l].sum+a[a[x].r].sum+1; a[x].d=d; } void rebuild(){ if(!rebid) return; bl(rebid); if(rebfa==0) {rebuild(root,1,now,a[rebid].d);} else{ if(a[rebfa].l==rebid) rebuild(a[rebfa].l,1,now,a[rebid].d); else rebuild(a[rebfa].r,1,now,a[rebid].d); } rebid=rebfa=now=0; } int query(int x,node k){ int ck=0,sum=0; if(!x) return 0; for(int i=0;i<3;i++) if(k.min[i]<=a[x].min[i]&&a[x].max[i]<=k.max[i]) ck++; if(ck==3) return a[x].sum; for(int i=0;i<3;i++) if(k.max[i]<a[x].min[i]||a[x].max[i]<k.min[i]) return 0; ck=0; for(int i=0;i<3;i++) if(k.min[i]<=a[x].a[i]&&a[x].a[i]<=k.max[i]) ck++; if(ck==3) sum++; return sum+query(a[x].l,k)+query(a[x].r,k); } int main(){ int n; scanf("%d",&n); while(n--){ int op,x,y,z,x1,y1,z1; scanf("%d%d%d%d",&op,&x,&y,&z); if(op==1) add(root,0,0,node(x,y,z)),rebuild(); else scanf("%d%d%d",&x1,&y1,&z1),printf("%d\n",query(root,node(x,y,z,x1,y1,z1))); } }