bzoj2716/2648 / P4169 [Violet]天使玩偶/SJY摆棋子
k-d tree 模板
找了好几天才发现输出优化错了....真是zz......
当子树非常不平衡时,就用替罪羊树的思想,拍扁重建。
luogu有个点开了O2才过.......
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cctype> 6 using namespace std; 7 char c;void read(int &x){ 8 c=getchar();x=0;int f=1; 9 while(!isdigit(c)) c=getchar(),f=(f&&c!='-'); 10 while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar(); 11 x=f?x:-x; 12 } 13 void print(int x){ 14 if(x<0) putchar('-'),x=-x; 15 if(x>9) print(x/10); 16 putchar(x%10+48); 17 } 18 inline int max(int a,int b){return a>b?a:b;} 19 inline int min(int a,int b){return a<b?a:b;} 20 inline int abs(int a){return a<0?-a:a;} 21 #define N 1000010 22 #define alph (0.75) 23 #define inf 1e9+7 24 int n,m,rt,u,ans; 25 int lit[N],tp1,tp2; 26 int d;struct node{ 27 int p[2]; 28 void init(){read(p[0]);read(p[1]);} 29 bool operator < (const node &t) const{ 30 return p[d]<t.p[d]; 31 } 32 }b[N]; 33 struct data{int mx[2],my[2],ch[2],sz,fa;node ad;}a[N]; 34 #define lc a[o].ch[0] 35 #define rc a[o].ch[1] 36 inline void up(int o){ 37 a[o].mx[0]=max(a[o].mx[0],max(a[lc].mx[0],a[rc].mx[0])); 38 a[o].mx[1]=min(a[o].mx[1],min(a[lc].mx[1],a[rc].mx[1])); 39 a[o].my[0]=max(a[o].my[0],max(a[lc].my[0],a[rc].my[0])); 40 a[o].my[1]=min(a[o].my[1],min(a[lc].my[1],a[rc].my[1])); 41 a[o].sz=a[lc].sz+a[rc].sz+1; 42 } 43 inline void news(int &o,node w){ 44 o=tp1?lit[tp1--]:++u; a[o].ad=w; 45 lc=rc=0; a[o].sz=1; 46 a[o].mx[0]=a[o].mx[1]=w.p[0]; 47 a[o].my[0]=a[o].my[1]=w.p[1]; 48 } 49 void build(int &o,int l,int r,int wd){ 50 if(l>r) return ; 51 int mid=l+((r-l)>>1); 52 d=wd;nth_element(b+l,b+mid,b+r+1); 53 news(o,b[mid]); 54 build(lc,l,mid-1,wd^1),a[lc].fa=o; 55 build(rc,mid+1,r,wd^1),a[rc].fa=o; 56 up(o); 57 } 58 void pia(int o){ 59 if(lc) pia(lc); 60 lit[++tp1]=o; b[++tp2]=a[o].ad; 61 if(rc) pia(rc); 62 } 63 inline void check(int &o,int wd){ 64 if(alph*a[o].sz<max(a[lc].sz,a[rc].sz)) 65 tp2=0,pia(o),build(o,1,tp2,wd); 66 }//是否不平衡需要重建 67 void ins(int &o,int wd,node w){ 68 if(!o) {news(o,w); return ;} 69 d=wd;ins(a[o].ch[a[o].ad<w],wd^1,w); 70 up(o);check(o,wd); 71 } 72 inline int gdis(int o,node w){ 73 if(!o) return inf; 74 int res=0; 75 if(w.p[0]>a[o].mx[0]) res+=w.p[0]-a[o].mx[0]; 76 if(w.p[0]<a[o].mx[1]) res+=a[o].mx[1]-w.p[0]; 77 if(w.p[1]>a[o].my[0]) res+=w.p[1]-a[o].my[0]; 78 if(w.p[1]<a[o].my[1]) res+=a[o].my[1]-w.p[1]; 79 return res; 80 }//点与矩形的最小距离 81 inline int dis(node A,node B){ 82 return abs(A.p[0]-B.p[0])+abs(A.p[1]-B.p[1]); 83 } 84 void query(int o,node w){ 85 if(!o) return ; 86 ans=min(ans,dis(a[o].ad,w)); 87 int D[2]={gdis(lc,w),gdis(rc,w)},r=D[0]>D[1]; 88 if(D[r]<ans) query(a[o].ch[r],w); 89 if(D[r^1]<ans) query(a[o].ch[r^1],w); 90 } 91 int main(){ 92 read(n);read(m); 93 a[0].mx[0]=a[0].my[0]=-inf; 94 a[0].mx[1]=a[0].my[1]=inf; 95 for(register int i=1;i<=n;++i) b[i].init(); 96 build(rt,1,n,0); node q1; 97 for(register int i=1,q2;i<=m;++i){ 98 read(q2); q1.init(); 99 if(q2==1) ins(rt,0,q1); 100 else{ 101 ans=inf,query(rt,q1); 102 print(ans); putchar('\n'); 103 } 104 }return 0; 105 }