HDU - 5992 ——Finding Hotels (KD樹求最近點)

題目鏈接:https://vjudge.net/contest/332630#problem/K

/*
HDU - 5992 KD樹求最近點
t組數據,n個酒店,m個客人
後接n行,給出酒店座標x,y,酒店價格w
m行,給出客人座標x,y。客人最大能接受價格w
求客人最大能接受價格內的最近酒店是哪個,距離相同時輸出,選擇順序靠前的酒店
輸出m行,第i個客人選擇的酒店座標,價格
1
3 3
1 1 1
3 2 3
2 3 2
2 2 1
2 2 2
2 2 3
ans:
1 1 1
2 3 2
3 2 3

把酒店價格當成第三個維度,建立三維KD樹,搜索滿足條件下的最近點
*/
#include<bits/stdc++.h>
#define M 200010
#define ll long long
using namespace std;
ll t,n,m,wb,x,y,z,rt,dis,ans;
ll sta[M],tot;
const ll inf=1e18;
struct point
{
    ll c[3],w,id;
    bool operator <  (const point a) const
    {
        return this->c[wb]<a.c[wb];
    }
} P[M];
struct node
{
    ll mi[3],mx[3],ls,rs;
    point tp;
} T[M];
void up(ll r)
{
    ll ls=T[r].ls,rs=T[r].rs;
    for(ll i=0; i<3; i++)
    {
        T[r].mi[i]=T[r].mx[i]=T[r].tp.c[i];
        if(ls)
        {
            T[r].mi[i]=min(T[r].mi[i],T[ls].mi[i]);
            T[r].mx[i]=max(T[r].mx[i],T[ls].mx[i]);
        }
        if(rs)
        {
            T[r].mi[i]=min(T[r].mi[i],T[rs].mi[i]);
            T[r].mx[i]=max(T[r].mx[i],T[rs].mx[i]);
        }
    }
}
ll build(ll l,ll r,ll k)//暴力建樹
{
    if(l>r) return 0;
    ll mid=(l+r)>>1,now=++tot;
    wb=k,nth_element(P+l,P+mid,P+r+1),T[now].tp=P[mid];
    T[now].ls=build(l,mid-1,(k+1)%3),T[now].rs=build(mid+1,r,(k+1)%3);
    up(now);
    return now;
}
ll getdis(ll rt)//返回點集中可能的最近點距離
{
    ll res=0;
    if(z<T[rt].mi[2]) return inf+1;
    if(x>T[rt].mx[0]) res+=(x-T[rt].mx[0])*(x-T[rt].mx[0]);
    if(x<T[rt].mi[0]) res+=(T[rt].mi[0]-x)*(T[rt].mi[0]-x);
    if(y>T[rt].mx[1]) res+=(y-T[rt].mx[1])*(y-T[rt].mx[1]);
    if(y<T[rt].mi[1]) res+=(T[rt].mi[1]-y)*(T[rt].mi[1]-y);
    return res;
}
void query(ll rt)
{
    ll dm=0,dl=inf+1,dr=inf+1,ls=T[rt].ls,rs=T[rt].rs;
    if(T[rt].tp.c[2]>z) dm=inf;
    if(dm==0)
    {
        dm = (T[rt].tp.c[0]-x)*(T[rt].tp.c[0]-x)+(T[rt].tp.c[1]-y)*(T[rt].tp.c[1]-y);
        if(dm<dis)
        {
            dis=dm;
            ans=rt;
        }
        else if(dm==dis)
        {
            ans = T[ans].tp.id < T[rt].tp.id ? ans:rt;
        }
    }
    if(ls) dl=getdis(ls);
    if(rs) dr=getdis(rs);
    if(dl<dr)
    {
        if(dl<=dis) query(ls);
        if(dr<=dis) query(rs);
    }
    else
    {
        if(dr<=dis) query(rs);
        if(dl<=dis) query(ls);
    }
}
int main()
{
    for(scanf("%lld",&t); t; t--)
    {
        tot=0;
        scanf("%lld%lld",&n,&m);
        for(ll i=1; i<=n; i++)
        {
            for(ll j=0; j<3; j++) scanf("%lld",&P[i].c[j]);
            P[i].id=i;
        }
        rt=build(1,n,0);
        for(ll i=1; i<=m; i++)
        {
            scanf("%lld%lld%lld",&x,&y,&z);
            dis=inf;
            query(rt);
            printf("%lld %lld %lld\n",T[ans].tp.c[0],T[ans].tp.c[1],T[ans].tp.c[2]);
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章