hdu5992(kdtree)

Finding Hotels

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)
Total Submission(s): 1709    Accepted Submission(s): 529


Problem Description
There are N hotels all over the world. Each hotel has a location and a price. M guests want to find a hotel with an acceptable price and a minimum distance from their locations. The distances are measured in Euclidean metric.
 

Input
The first line is the number of test cases. For each test case, the first line contains two integers N (N ≤ 200000) and M (M ≤ 20000). Each of the following N lines describes a hotel with 3 integers x (1 ≤ x ≤ N), y (1 ≤ y ≤ N) and c (1 ≤ c ≤ N), in which x and y are the coordinates of the hotel, c is its price. It is guaranteed that each of the N hotels has distinct x, distinct y, and distinct c. Then each of the following M lines describes the query of a guest with 3 integers x (1 ≤ x ≤ N), y (1 ≤ y ≤ N) and c (1 ≤ c ≤ N), in which x and y are the coordinates of the guest, c is the maximum acceptable price of the guest.
 

Output
For each guests query, output the hotel that the price is acceptable and is nearest to the guests location. If there are multiple hotels with acceptable prices and minimum distances, output the first one.
 

Sample Input
 
  
2 3 3 1 1 1 3 2 3 2 3 2 2 2 1 2 2 2 2 2 3 5 5 1 4 4 2 1 2 4 5 3 5 2 1 3 3 5 3 3 1 3 3 2 3 3 3 3 3 4 3 3 5
 

Sample Output
 
  
1 1 1 2 3 2 3 2 3 5 2 1 2 1 2 2 1 2 1 4 4 3 3 5
 

题意:给出在二维坐标系中的n个点,每个点都有花费。接下来m个查询,每个查询给出二维坐标系中的一个点和容许最大花费c,要求在最大花费容许情况下求出距离查询的点最近的点,如果多个点距离相同,给出输入顺序中最前的一个点。

思路:kdtree,把二维坐标和花费组合为3个维度。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 200005;
const ll INF = 1ll<<60;
struct node
{
    int Min[3],Max[3];  //表示这个点控制的几个维度的最大范围
    int d[3];           //这个点在空间中的位置
    int l,r;            //左右儿子
    int id;             //输入顺序编号
}t[maxn];
int nowD;               //表示当前讨论的是哪一个维度
int x,y,c;
int ans;                //存储结果编号
ll dist;                //存储结果距离
ll getdist(int p)       //获取p点控制范围与查询点之间的距离
{
    if(t[p].Min[2]>c)return INF;   //如果p点控制范围所有点花费过大
    ll dis=0;
    if(x<t[p].Min[0]) dis+=1ll*(t[p].Min[0]-x)*(t[p].Min[0]-x);
    if(x>t[p].Max[0]) dis+=1ll*(t[p].Max[0]-x)*(t[p].Max[0]-x);
    if(y<t[p].Min[1]) dis+=1ll*(t[p].Min[1]-y)*(t[p].Min[1]-y);
    if(y>t[p].Max[1]) dis+=1ll*(t[p].Max[1]-y)*(t[p].Max[1]-y);
    return dis;
}
bool cmp(node a,node b)
{
    return a.d[nowD]<b.d[nowD];
}
void kd_updata(int now)   //由子节点控制范围来更新now点的控制范围
{
    if(t[now].l)
    {
        if(t[t[now].l].Max[0]>t[now].Max[0]) t[now].Max[0]=t[t[now].l].Max[0];
        if(t[t[now].l].Max[1]>t[now].Max[1]) t[now].Max[1]=t[t[now].l].Max[1];
        if(t[t[now].l].Max[2]>t[now].Max[2]) t[now].Max[2]=t[t[now].l].Max[2];
        if(t[t[now].l].Min[0]<t[now].Min[0]) t[now].Min[0]=t[t[now].l].Min[0];
        if(t[t[now].l].Min[1]<t[now].Min[1]) t[now].Min[1]=t[t[now].l].Min[1];
        if(t[t[now].l].Min[2]<t[now].Min[2]) t[now].Min[2]=t[t[now].l].Min[2];
    }
    if(t[now].r)
    {
        if(t[t[now].r].Max[0]>t[now].Max[0]) t[now].Max[0]=t[t[now].r].Max[0];
        if(t[t[now].r].Max[1]>t[now].Max[1]) t[now].Max[1]=t[t[now].r].Max[1];
        if(t[t[now].r].Max[2]>t[now].Max[2]) t[now].Max[2]=t[t[now].r].Max[2];
        if(t[t[now].r].Min[0]<t[now].Min[0]) t[now].Min[0]=t[t[now].r].Min[0];
        if(t[t[now].r].Min[1]<t[now].Min[1]) t[now].Min[1]=t[t[now].r].Min[1];
        if(t[t[now].r].Min[2]<t[now].Min[2]) t[now].Min[2]=t[t[now].r].Min[2];
    }
}
int kd_build(int l,int r,int D)   //kd树的建立
{
    int mid=(l+r)>>1;
    nowD=D;
    nth_element(t+l,t+mid,t+r+1,cmp);
    if(l!=mid) t[mid].l=kd_build(l,mid-1,(D+1)%3);else t[mid].l=0;
    if(r!=mid) t[mid].r=kd_build(mid+1,r,(D+1)%3);else t[mid].r=0;
    t[mid].Max[0]=t[mid].Min[0]=t[mid].d[0];
    t[mid].Max[1]=t[mid].Min[1]=t[mid].d[1];
    t[mid].Max[2]=t[mid].Min[2]=t[mid].d[2];
    kd_updata(mid);
    return mid;
}
void kd_query(int p)   //查询
{
    ll dl=INF,dr=INF,d0=INF;
    if(t[p].d[2]<=c) d0=1ll*(t[p].d[0]-x)*(t[p].d[0]-x)+1ll*(t[p].d[1]-y)*(t[p].d[1]-y);
    if(d0<dist||d0==dist&&t[p].id<t[ans].id)
    {
        ans=p;
        dist=d0;
    }
    if(t[p].l) dl=getdist(t[p].l);
    if(t[p].r) dr=getdist(t[p].r);
    if(dl<dr)
    {
        if(dl<=dist) kd_query(t[p].l);
        if(dr<=dist) kd_query(t[p].r);
    }
    else
    {
        if(dr<=dist) kd_query(t[p].r);
        if(dl<=dist) kd_query(t[p].l);
    }
}

inline int getint()
{
    int w=0,q=0;
    char c=getchar();
    while((c<'0'||c>'9')&&c!='-') c=getchar();
    if(c=='-') q=1,c=getchar();
    while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
    return q?-w:w;
}
int main()
{
    int cas;
    int n,m;
    cas=getint();
    while(cas--)
    {
        n=getint();m=getint();
        for(int i=1;i<=n;i++)
        {
            t[i].d[0]=getint();
            t[i].d[1]=getint();
            t[i].d[2]=getint();
            t[i].id = i;
        }
        int rt = kd_build(1,n,0);
        while(m--)
        {
            ans=0;
            dist=INF;
            x=getint();y=getint();c=getint();
            kd_query(rt);
            printf("%d %d %d\n",t[ans].d[0],t[ans].d[1],t[ans].d[2]);
        }
    }
}








猜你喜欢

转载自blog.csdn.net/qq_25576697/article/details/80976904