题意:初始给定一些点,两种操作:1.询问一个点的最近点 2.加点
替罪羊kdtree即可,由于这题是我第一次写kdtree找最近点,查询写崩了,用读入优化卡时过的。。。
而且中途出现了很多问题:
1.树为空要返回0,要不就崩了
2.建树时记得更新size
3.初始50W个点,操作50W次,最多可能有100W个点
4.nth_element的比较函数我穿了个小于等于进去。。。无限RE
#include<cstdio>
#include<cmath>
#include<algorithm>
using std::nth_element;
inline int abs(int a)
{
return a<0?-a:a;
}
struct pnt
{
int p[2];
pnt(int a=0,int b=0){p[0]=a,p[1]=b;}
int& operator [](size_t x){return p[x];}
const int& operator [](size_t x) const {return p[x];}
inline bool operator == (const pnt &b) const{return p[0]==b[0]&&p[1]==b[1];}
friend inline int __dis(const pnt &a,const pnt &b)
{
return abs(a[0]-b[0])+abs(a[1]-b[1]);
}
};
inline bool cmp0(const pnt &a,const pnt &b)
{
return a[0]<=b[0];
}
inline bool cmp1(const pnt &a,const pnt &b)
{
return a[1]<=b[1];
}
bool(*cmp[2])(const pnt&,const pnt&)={cmp0,cmp1};
inline int __min(int a,int b){return a<b?a:b;}
inline void min(int &a,int b){if(b<a) a=b;}
inline void max(int &a,int b){if(a<b) a=b;}
inline void min(pnt &a,const pnt &b){min(a[0],b[0]),min(a[1],b[1]);}
inline void max(pnt &a,const pnt &b){max(a[0],b[0]),max(a[1],b[1]);}
struct node
{
pnt v,mn,mx;
node *l,*r;
size_t sz;
node(const pnt &v):v(v),mn(v),mx(v),l(0),r(0),sz(1){}
inline void up()
{
if(l) min(mn,l->mn),max(mx,l->mx),sz+=l->sz;
if(r) min(mn,r->mn),max(mx,r->mx),sz+=r->sz;
}
inline void up(const pnt &p)
{
min(mn,p),max(mx,p);
}
inline int min_dis(const pnt &p)
{
if(!this) return 0x7fffffff;
int x,y;
if(cmp0(mn,p)&&cmp0(p,mx)) x=0;
else x=__min(abs(p[0]-mn[0]),abs(mx[0]-p[0]));
if(cmp1(mn,p)&&cmp1(p,mx)) y=0;
else y=__min(abs(p[1]-mn[1]),abs(mx[1]-p[1]));
return x+y;
}
inline void* operator new (size_t)
{
static unsigned char pool[1000000*sizeof(node)];
static size_t k=-1;
return (node*)pool+ ++k;
}
inline void reset()
{
mn=mx=v;
sz=1;
}
int check(const pnt &p,bool k)
{
if(!this) return 0x7fffffff;
int res=__dis(p,v);
if(!res) return 0;
bool way=cmp[k](v,p);
min(res,(way?r:l)->check(p,!k));
if((way?l:r)->min_dis(p)<res)
min(res,(way?l:r)->check(p,!k));
return res;
}
}*ar[500000];
inline bool node_cmp0(node* a,node* b)
{
return a->v[0]<b->v[0];
}
inline bool node_cmp1(node *a,node *b)
{
return a->v[1]<b->v[1];
}
bool(*node_cmp[2])(node*,node*)={node_cmp0,node_cmp1};
int top;
const double A=0.7,B=log(1.0/0.7);
struct kdtree
{
node *rt;
bool bad;
kdtree():rt(0),bad(0){}
void tour(node *x)
{
if(!x) return;
x->reset();
tour(x->l);
ar[++top]=x;
tour(x->r);
}
void rebuild(node*& x,bool k,int l,int r)
{
if(r<l) {x=0;return;}
int mid=l+r>>1;
nth_element(ar+l,ar+mid,ar+r+1,node_cmp[k]);
x=ar[mid];
rebuild(x->l,!k,l,mid-1);
rebuild(x->r,!k,mid+1,r);
x->up();
}
inline void rebuild(node*& x,bool k)
{
top=-1;
tour(x);
rebuild(x,k,0,top);
}
inline int query(int x,int y)
{
return rt->check(pnt(x,y),0);
}
bool insert(node*& x,const pnt &p,bool k,size_t h)
{
if(!x)
{
x=new node(p);
bad=h>log(rt->sz)/B;
return 1;
}
if(x->v==p) return 0;
if(cmp[k](p,x->v))
{
bool kre=insert(x->l,p,!k,h+1);
x->sz+=kre;
if(bad&&x->l->sz>x->sz*A) rebuild(x,k),bad=0;
if(kre) x->up(p);
return kre;
}
else
{
bool kre=insert(x->r,p,!k,h+1);
x->sz+=kre;
if(bad&&x->r->sz>x->sz*A) rebuild(x,k),bad=0;
if(kre) x->up(p);
return kre;
}
}
inline void insert(int x,int y)
{
insert(rt,pnt(x,y),0,0);
}
}tr;
int n,m,t,x,y;
const size_t str=1<<20;
struct Istream
{
unsigned char buf[str],*s,*t;
Istream():buf(),s(),t(){}
inline unsigned char get()
{
if(s==t) t=buf+fread(s=buf,1,str-1,stdin);
return *s++;
}
inline Istream& operator >> (int &x)
{
register unsigned char c;
x=0;
do c=get(); while(c<'0'||c>'9');
while(c>='0'&&c<='9') x=x*10+c-'0',c=get();
return *this;
}
}cin;
struct Ostream
{
unsigned char buf[str],*s,*t;
Ostream():buf(),s(buf),t(buf+str-1){}
~Ostream(){fwrite(buf,1,s-buf,stdout);}
inline void put(unsigned char c)
{
if(s==t) fwrite(s=buf,1,str-1,stdout);
*s++=c;
}
inline Ostream& operator << (const int &x)
{
static int a[15],t;
if(!x) return put('0'),put('\n'),*this;
a[t=1]=x;
while(a[t]) a[t+1]=a[t]/10,a[t++]%=10;
while(--t) put(a[t]+'0');
return put('\n'),*this;
}
}cout;
int main()
{
//freopen("angel.in","r",stdin);
//freopen("angel.out","w",stdout);
cin>>n>>m;
for(int i=1;i<=n;++i)
{
cin>>x>>y;
tr.insert(x,y);
}
for(int i=1;i<=m;++i)
{
cin>>t>>x>>y;
if(t==1) tr.insert(x,y);
else cout<<tr.query(x,y);
}
return 0;
}