题目链接
说起来k-d tree这玩意也很暴力啊
建树的话每次取剩下数列下一维中位数的点做儿子(其实随机哪维也行,就跟点分找重心一样,这只是一个复杂度的问题
查询就是一个暴力剪枝
估价为这个子树代表的包含所有点的矩形离查询点的最近距离(具体方法一言难尽,直接看估价函数就好懂了
插入就直接二分插入,但是这样显然是会被卡成链之类的东西的,显然像替罪羊树一样定期重构就可以了
#include<bits/stdc++.h>
#define alpha 0.8
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline long long read() { long long f=1,x=0;char ch; do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9'); do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9'); return f*x; }
struct dd
{
long long d[2];
}tmp[500010];
struct kdtree
{
int son[2],mi[2],mx[2],sz;
dd p;
}t[2000010];
int cnt,D,sta[2000030],top,tot;
int n,m,rt;
int cmp(dd a,dd b)
{
return a.d[D]<b.d[D];
}
inline int bad(int now)
{
return alpha*t[now].sz<max(t[t[now].son[0]].sz,t[t[now].son[1]].sz);
}
inline int newnode()
{
if(top) return sta[top--];
else return ++tot;
}
void push_up(int now)
{
int l=t[now].son[0];
int r=t[now].son[1];
for(int i=0;i<=1;i++)
{
t[now].mi[i]=t[now].mx[i]=t[now].p.d[i];
if(l) t[now].mi[i]=min(t[now].mi[i],t[l].mi[i]),t[now].mx[i]=max(t[now].mx[i],t[l].mx[i]);
if(r) t[now].mi[i]=min(t[now].mi[i],t[r].mi[i]),t[now].mx[i]=max(t[now].mx[i],t[r].mx[i]);
}
t[now].sz=t[l].sz+t[r].sz+1;
}
void pia(int now)
{
if(!now) return ;
pia(t[now].son[0]);
tmp[++cnt]=t[now].p;
sta[++top]=now;
pia(t[now].son[1]);
}
void la(int l,int r,int &now,int d)
{
if(l>r) {now=0;return ;}
int mid=(l+r)>>1;
D=d,nth_element(tmp+l,tmp+mid,tmp+r+1,cmp);
now=newnode();
t[now].p=tmp[mid];
la(l,mid-1,t[now].son[0],d^1);
la(mid+1,r,t[now].son[1],d^1);
push_up(now);
}
void rebuild(int &now)
{
cnt=0;
pia(now);
if(cnt>0) la(1,cnt,now,0);
}
void insert(int &now,int d,dd pp)
{
if(!now)
{
now=newnode();
t[now].p=pp;
t[now].son[0]=t[now].son[1]=0;
push_up(now);
return ;
}
if(t[now].p.d[d]>=pp.d[d]) insert(t[now].son[0],d^1,pp);
else insert(t[now].son[1],d^1,pp);
push_up(now);
if(bad(now)) rebuild(now);
}
inline int get_dis(int now,dd pp)
{
int dis=0;
for(int i=0;i<=1;i++)
{
dis+=max(t[now].mi[i]-pp.d[i],0ll)+max(pp.d[i]-t[now].mx[i],0ll);
}
return dis;
}
long long dist(dd a,dd b)
{
return abs(a.d[0]-b.d[0])+abs(a.d[1]-b.d[1]);
}
long long ans=inf;
void query(int now,dd pp)
{
ans=min(ans,dist(t[now].p,pp));
long long d1=inf,d2=inf;
if(t[now].son[0]) d1=get_dis(t[now].son[0],pp);
if(t[now].son[1]) d2=get_dis(t[now].son[1],pp);
if(d1<=d2)
{
if(d1<ans) query(t[now].son[0],pp);
if(d2<ans) query(t[now].son[1],pp);
}
else
{
if(d2<ans) query(t[now].son[1],pp);
if(d1<ans) query(t[now].son[0],pp);
}
}
int kd,l,r;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
tmp[i].d[0]=read();
tmp[i].d[1]=read();
}
la(1,n,rt,0);
dd tmp1;
for(int i=1;i<=m;i++)
{
kd=read();
tmp1.d[0]=read();
tmp1.d[1]=read();
if(kd==1) insert(rt,0,tmp1);
else ans=inf,query(rt,tmp1),printf("%lld\n",ans);
}
}