BZOJ 2648: SJY擺棋子(kd tree)
阿新 • • 發佈:2018-11-22
題目:https://www.lydsy.com/JudgeOnline/problem.php?id=2648
#include<bits/stdc++.h> using namespace std; const int inf = 0x3f3f3f3f; const int maxn=1e6+100; int idx,n,m,tol,ans; struct node { int x[2],ls,rs,mn[2],mx[2]; bool operator<(const node &u) const { return x[idx]<u.x[idx]; } }P[maxn]; struct KD_TREE { node p[maxn]; void update(int rt) { int lc=p[rt].ls,rc=p[rt].rs; if(lc) { for(int i=0;i<2;i++) { p[rt].mn[i]=min(p[rt].mn[i],p[lc].mn[i]); p[rt].mx[i]=max(p[rt].mx[i],p[lc].mx[i]); } } if(rc) { for(int i=0;i<2;i++) { p[rt].mn[i]=min(p[rt].mn[i],p[rc].mn[i]); p[rt].mx[i]=max(p[rt].mx[i],p[rc].mx[i]); } } } int build(int l,int r,int dep) { if(l>r) return 0; int rt=++tol; int mid=(l+r)/2; idx=dep; nth_element(P+l,P+mid,P+r+1); p[rt]=P[mid]; p[rt].ls=build(l,mid-1,dep^1); p[rt].rs=build(mid+1,r,dep^1); update(rt); return rt; } void update1(int rt,node a) { for(int i=0;i<2;i++) { p[rt].mn[i]=min(p[rt].mn[i],a.x[i]); p[rt].mx[i]=max(p[rt].mx[i],a.x[i]); } } void Insert(int rt,int dep,node a) { int lc=p[rt].ls,rc=p[rt].rs; update1(rt,a); if(a.x[dep]>=p[rt].x[dep]) { if(lc) Insert(lc,dep^1,a); else { p[rt].ls=lc=++tol; p[lc]=a; return; } } else { if(rc) Insert(rc,dep^1,a); else { p[rt].rs=rc=++tol; p[rc]=a; return; } } } int dist(int rt,node a) { int dis=0; for(int i=0;i<2;i++) { if(a.x[i]<p[rt].mn[i]) dis+=(p[rt].mn[i]-a.x[i]); if(a.x[i]>p[rt].mx[i]) dis+=(a.x[i]-p[rt].mx[i]); } return dis; } void query(int rt,node a) { if(rt==0) return; ans=min(ans,abs(a.x[0]-p[rt].x[0])+abs(a.x[1]-p[rt].x[1])); int dl=inf,dr=inf; if(p[rt].ls) dl=dist(p[rt].ls,a); if(p[rt].rs) dr=dist(p[rt].rs,a); if(min(dl,dr)>=ans) return; if(dl<dr) { query(p[rt].ls,a); if(dr<ans) query(p[rt].rs,a); } else { query(p[rt].rs,a); if(dl<ans) query(p[rt].ls,a); } } }KDT; int main() { scanf("%d%d",&n,&m); for(int i=0;i<n;i++) { scanf("%d%d",&P[i].x[0],&P[i].x[1]); P[i].mn[0]=P[i].mx[0]=P[i].x[0]; P[i].mn[1]=P[i].mx[1]=P[i].x[1]; P[i].ls=P[i].rs=0; } int root=KDT.build(0,n-1,0); while(m--) { int op;node now;scanf("%d%d%d",&op,&now.x[0],&now.x[1]); for(int i=0;i<2;i++) now.mn[i]=now.mx[i]=now.x[i]; now.ls=now.rs=0; if(op==1) { if(root==0) { root=++tol; KDT.p[root]=now; continue; } KDT.Insert(root,0,now); } else { ans=inf; KDT.query(root,now); printf("%d\n",ans); } } return 0; }