传送门: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;
}