KDtree可以快速求多维空间一个点离他最近的点。
这个题是HDU5992.裸的KD-tree
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=1e9+7;
int root,n,m,key;ll len;
ll sqr(ll x)
{
return x*x;
}
struct node
{
int son[2],mi[3],mx[3],d[3],id;
friend bool operator <(node a,node b)
{
return a.d[key]<b.d[key];
}
friend ll dis(node a,node b)
{
return sqr(a.d[1]-b.d[1])+sqr(a.d[0]-b.d[0]);
}
}po,ans;
struct kdtree
{
node a[200010];
void init()
{
a[0].son[0]=a[0].son[1]=0;
for (int i=0; i<3; i++)
{
a[0].mi[i]=inf;
a[0].mx[i]=-inf;
}
}
void update(int x)
{
int l=a[x].son[0],r=a[x].son[1];
for (int i=0; i<3; i++)
{
a[x].mi[i]=min(a[x].d[i],min(a[l].mi[i],a[r].mi[i]));
a[x].mx[i]=max(a[x].d[i],max(a[l].mx[i],a[r].mx[i]));
}
}
int build(int l,int r,int cur)
{
if (l>r) return 0;
int m=(l+r)>>1;
key=cur; nth_element(a+l,a+m,a+r+1);
a[m].son[0]=build(l,m-1,cur^1);
a[m].son[1]=build(m+1,r,cur^1);
update(m);
return m;
}
void check(int q)
{
if(a[q].d[2]>po.d[2])return;
ll l=dis(a[q],po);
if((len>l)||(len==l&&a[q].id<ans.id))
{
ans=a[q];
len=l;
}
}
ll get(int q)
{
if(!q||a[q].mi[2]>po.d[2])return 1e18+5;
ll res=0;
for(int i=0;i<2;i++)
{
res+=sqr(max(0,po.d[i]-a[q].mx[i]));
res+=sqr(max(0,a[q].mi[i]-po.d[i]));
}
return res;
}
void ask(int q)
{
if(a[q].mi[2]>po.d[2])return;
check(q);
int l=a[q].son[0],r=a[q].son[1];
ll dl=get(l),dr=get(r);
if(dl<dr)
{
if(dl<=len)ask(l);
if(dr<=len)ask(r);
}
else
{
if(dr<=len)ask(r);
if(dl<=len)ask(l);
}
}
} kd;
int main()
{
kd.init();
int t;scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for (int i=1; i<=n; i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
kd.a[i].d[0]=x;
kd.a[i].d[1]=y;
kd.a[i].d[2]=z;
kd.a[i].id=i;
}
root=kd.build(1,n,0);
while(m--)
{
scanf("%d%d%d",&po.d[0],&po.d[1],&po.d[2]);
len=1e18;kd.ask(root);
printf("%d %d %d\n",ans.d[0],ans.d[1],ans.d[2]);
}
}
return 0;
}