题意是说有T组样例输入,然后输入N和M,N是旅馆的个数,M是游客的个数。假设旅馆中来多少人都能住开,接下来N行分别是旅馆的位置x,y和旅馆的价格c,然后M行分别是这些人现在的位置和他们所带的钱。要求输出离每个人最近且这个人能付起这个旅馆房费的旅馆(只要付得起就行,不用考虑价格高低)。如果有很多旅馆同时满足要求,就输出样例中先输入进去的那一个旅馆。
这个题几乎是KD树的一个模板题,只是多加了价格的限制以及最后处理一下旅馆顺序进行输出。抛开这些就是一个求最近距离的KD树问题。也是之前从来没见过这个算法,看了一下,其实和线段树也差不多,只是在处理上这是一个多维的二叉搜索树,进行多维查询,具体的就不多说了,因为对于KD树我自己其实也没太深入看懂= =临近区域赛,从网上找了份题解先看懂了,记录一下为比赛准备模板~
下面AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<climits>
using namespace std;
long long n,m;
long long cmp_d;
long long root;
struct node
{
long long l,r;
long long d[3],Max[3],Min[3];
long long id;
};
node a[200005];
bool cmp(node a,node b)
{
return a.d[cmp_d]<b.d[cmp_d];
}
int up(long long p,long long k)
{
int i;
for(i=0;i<3;i++)
{
a[p].Min[i]=min(a[p].Min[i],a[k].Min[i]);
a[p].Max[i]=max(a[p].Max[i],a[k].Max[i]);
}
return 0;
}
long long build(long long l,long long r,long long D)
{
int i;
cmp_d=D;
long long mid=(l+r)/2;
nth_element(a+1+l,a+1+mid,a+1+r,cmp);
for(i=0;i<3;i++)
a[mid].Min[i]=a[mid].Max[i]=a[mid].d[i];
if(l!=mid)
a[mid].l=build(l,mid-1,(D+1)%3);
else
a[mid].l=0;
if(r!=mid)
a[mid].r=build(mid+1,r,(D+1)%3);
else
a[mid].r=0;
if(a[mid].r)
up(mid,a[mid].r);
if(a[mid].l)
up(mid,a[mid].l);
return mid;
}
long long x,y,z;
long long jl,ans;
long long getdis(long long p)
{
long long res=0;
if(z<a[p].Min[2])
return LLONG_MAX;
if(x>a[p].Max[0])
res+=(x-a[p].Max[0])*(x-a[p].Max[0]);
if(x<a[p].Min[0])
res+=(a[p].Min[0]-x)*(a[p].Min[0]-x);
if(y>a[p].Max[1])
res+=(y-a[p].Max[1])*(y-a[p].Max[1]);
if(y<a[p].Min[1])
res+=(a[p].Min[1]-y)*(a[p].Min[1]-y);
return res;
}
int ask(long long p)
{
long long d0=0;
long long dl,dr;
if(a[p].d[2]>z)
d0+=LLONG_MAX;
else
{
d0+=(a[p].d[0]-x)*(a[p].d[0]-x)+(a[p].d[1]-y)*(a[p].d[1]-y);
if(d0<jl)
{
ans=p;
jl=d0;
}
else if(d0==jl)
{
if(a[p].id<a[ans].id)
{
ans=p;
}
}
}
if(a[p].l)
dl=getdis(a[p].l);
else
dl=LLONG_MAX;
if(a[p].r)
dr=getdis(a[p].r);
else
dr=LLONG_MAX;
if(dl<dr)
{
if(dl<=jl)
ask(a[p].l);
if(dr<=jl)
ask(a[p].r);
}
else
{
if(dr<=jl)
ask(a[p].r);
if(dl<=jl)
ask(a[p].l);
}
return 0;
}
int main()
{
int T;
int i,j;
scanf("%d",&T);
while(T--)
{
scanf("%lld%lld",&n,&m);
for(i=1;i<=n;i++)
{
for(j=0;j<3;j++)
{
scanf("%lld",&a[i].d[j]);
}
a[i].l=a[i].r=0;
a[i].id=i;
}
root=build(1,n,0);
for(i=1;i<=m;i++)
{
scanf("%lld%lld%lld",&x,&y,&z);
jl=LLONG_MAX;
ans=-1;
ask(root);
cout<<a[ans].d[0]<<" "<<a[ans].d[1]<<" "<<a[ans].d[2]<<endl;
}
}
return 0;
}