HDU - 5992 Finding Hotels (KD树)

版权声明:本文为蒟蒻原创文章,转载请注明出处哦~ https://blog.csdn.net/a54665sdgf/article/details/82942423

题目链接

题目大意:有n个旅馆,每个旅馆有三个参数x,y,c,分别代表旅馆的坐标和需要花的钱。有m个人想住这些旅馆,给你每个人的坐标和钱数,求出每个人能住进的离他最近的旅馆,如果有多个旅馆,则选择下标最小的。

解法:此题属于二维区间的极值查询问题,可以对每个旅馆的x坐标和y坐标轮流二分,建立一棵KD树,然后启发式搜索+剪枝。

#define FRER() freopen("i.txt","r",stdin)
#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const ll linf=0x3f3f3f3f3f3f3f3f;
const int N=2e5+10;
const int M=2e4+10;
struct node
{
    ll x[2];
    int c,i;
    node(ll x0=0,ll x1=0,int c_=0,int i_=0):x(
    {
        x0,x1
    }),c(c_),i(i_) {}
} hotel[N],person[M];
int n,m;
ll mindis;
int index,ansi;

ll dist(const node& a,const node& b)
{
    return (a.x[0]-b.x[0])*(a.x[0]-b.x[0])+(a.x[1]-b.x[1])*(a.x[1]-b.x[1]);
}

void build(int l,int r,int dim)
{
    if(l>=r)return;
    int mid=(l+r)>>1;
    nth_element(hotel+l,hotel+mid,hotel+r+1,[dim](const node& a,const node& b)
    {
        return a.x[dim]<b.x[dim];
    });
    build(l,mid-1,dim^1);
    build(mid+1,r,dim^1);
}

void query(const node& p,int l,int r,int dim)
{
    if(l>r)return;
    int mid=(l+r)>>1;
    ll dis=dist(p,hotel[mid]);
    if(hotel[mid].c<=p.c&&(dis<mindis||(dis==mindis&&hotel[mid].i<index)))
    {
        mindis=dis,index=hotel[mid].i,ansi=mid;
    }
    if(hotel[mid].x[dim]<p.x[dim])
    {
        query(p,mid+1,r,dim^1);
        if((hotel[mid].x[dim]-p.x[dim])*(hotel[mid].x[dim]-p.x[dim])<mindis)query(p,l,mid-1,dim^1);
    }
    else
    {
        query(p,l,mid-1,dim^1);
        if((hotel[mid].x[dim]-p.x[dim])*(hotel[mid].x[dim]-p.x[dim])<mindis)query(p,mid+1,r,dim^1);
    }
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0; i<n; ++i)
        {
            scanf("%lld%lld%d",&hotel[i].x[0],&hotel[i].x[1],&hotel[i].c);
            hotel[i].i=i;
        }
        build(0,n-1,0);
        while(m--)
        {
            mindis=linf;
            ll x0,x1;
            int c_;
            scanf("%lld%lld%d",&x0,&x1,&c_);
            query(node(x0,x1,c_,0),0,n-1,0);
            printf("%lld %lld %d\n",hotel[ansi].x[0],hotel[ansi].x[1],hotel[ansi].c);
        }
    }
    return 0;
}

ps:由于此题的数据不是很刁钻,因此直接从中间向两边暴搜也可以过。

猜你喜欢

转载自blog.csdn.net/a54665sdgf/article/details/82942423