HDU 5992 Finding Hotels KDtree

来源:互联网 发布:自动归类的软件 编辑:程序博客网 时间:2024/05/19 13:07

    题意是说有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;}