传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2648 http://www.lydsy.com/JudgeOnline/problem.php?id=2716
果然kdtree写的太丑了……而且慢的像toushi
似乎是否进入另一颗子树只是一个估价函数?
Code:
#include<cstdio> #include<iostream> #include<algorithm> #include<cctype> #include<climits> #include<cmath> using namespace std; const int maxn=500005; int n,m,D; int getint(){ int res=0,f=1;char c=getchar(); while(!isdigit(c))f=f==-1||c=='-'?-1:1,c=getchar(); while(isdigit(c))res=res*10+c-'0',c=getchar(); return res*f; } struct point{ int d[2],mn[2],mx[2],l,r; int& operator[](int i){return d[i];} bool operator<(point p)const{return d[D]<p[D];} point(int _x=0,int _y=0): l(0),r(0){d[0]=_x,d[1]=_y;} }p[maxn]; int dis(point a,point b){return abs(a[0]-b[0])+abs(a[1]-b[1]);} struct kdtree{ int root,ans; point P; point t[maxn<<1]; void rz(int p){ for(int i=0;i<2;i++){ if(t[p].l)t[p].mn[i]=min(t[p].mn[i],t[t[p].l].mn[i]), t[p].mx[i]=max(t[p].mx[i],t[t[p].l].mx[i]); if(t[p].r)t[p].mn[i]=min(t[p].mn[i],t[t[p].r].mn[i]), t[p].mx[i]=max(t[p].mx[i],t[t[p].r].mx[i]); } } int build(int l,int r,int dd){ D=dd;int mid=(l+r)>>1; nth_element(p+l,p+mid,p+r+1); t[mid]=p[mid]; for(int i=0;i<2;i++)t[mid].mn[i]=t[mid].mx[i]=t[mid][i]; if(l<mid)t[mid].l=build(l,mid-1,dd^1); if(r>mid)t[mid].r=build(mid+1,r,dd^1); rz(mid); return mid; } void insert(int p,int dd){ if(P[dd]>=t[p][dd]){ if(t[p].r)insert(t[p].r,dd^1); else{ t[p].r=++n; t[n]=P; for(int i=0;i<2;i++)t[n].mn[i]=t[n].mx[i]=t[n][i]; } }else{ if(t[p].l)insert(t[p].l,dd^1); else{ t[p].l=++n; t[n]=P; for(int i=0;i<2;i++)t[n].mn[i]=t[n].mx[i]=t[n][i]; } }rz(p); } int dist(int p1,point p){ int ans=0; for(int i=0;i<2;i++) ans+=max(0,t[p1].mn[i]-p[i]); for(int i=0;i<2;i++) ans+=max(0,p[i]-t[p1].mx[i]); return ans; } void QkNN(int p,int dd){ int dl,dr,d0; d0=dis(t[p],P); if(d0<ans)ans=d0; if(t[p].l)dl=dist(t[p].l,P);else dl=0x7f7f7f7f; if(t[p].r)dr=dist(t[p].r,P);else dr=0x7f7f7f7f; if(dl<dr){ if(dl<ans)QkNN(t[p].l,dd^1); if(dr<ans)QkNN(t[p].r,dd^1); }else{ if(dr<ans)QkNN(t[p].r,dd^1); if(dl<ans)QkNN(t[p].l,dd^1); } } void insert(point _p){P=_p;insert(root,0);} void init(){root=build(1,n,0);} int QkNN(point _p){P=_p;ans=INT_MAX;QkNN(root,0);return ans;} }T; int main(){ n=getint();m=getint(); for(int i=1;i<=n;i++)p[i][0]=getint(),p[i][1]=getint(); T.init(); while(m--){ int op=getint(),x=getint(),y=getint(); if(op==1)T.insert(point(x,y)); else printf("%d\n",T.QkNN(point(x,y))); } return 0; }