HDU5992 Finding Hotels(Kd-tree)

Finding Hotels

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


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


Source
2016ACM/ICPC亚洲区青岛站-重现赛(感谢中国石油大学)
当时知道是用kd树来做的,然后套了个模板加个加速挂还是t了。
第一次接触,然后很多地方都没考虑到,导致超时。
现在再来看一次,虽然用的依旧是模板,不过以后遇到心里也大概能有个底。
题意就是给你几个酒店的二维坐标和该酒店的花费,然后给你几个客人的坐标和他们能承受的最低消费,
然后分别找出各个客人在满足最低花费的情况下的酒店的欧式距离最短.
如果有多个,输出第一个(按输入顺序)
很明显,赤裸裸的kd-tree.

   安利一篇kd-tree学习的文章:传送门

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<ctime>
#include<string>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#include<set>
#include<map>
#include<cstdio>
#include<limits.h>
#define MOD 1000000007
#define fir first
#define sec second
#define fin freopen("/home/ostreambaba/文档/input.txt", "r", stdin)
#define fout freopen("/home/ostreambaba/文档/output.txt", "w", stdout)
#define mes(x, m) memset(x, m, sizeof(x))
#define Pii pair<int, int>
#define Pll pair<ll, ll>
#define INF 1e9+7
#define inf 0x3f3f3f3f

#define Pi 4.0*atan(1.0)
#define Sqrt(x) (x)*(x)

#define lowbit(x) (x&(-x))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-12;
const int maxn = 200000+10;
using namespace std;
inline int read(){
    int x(0),f(1);
    char ch=getchar();
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int idx;
struct node{
    int f[3];
    int id; //标记多个最短距离取第一个输入的数据
    bool operator<(const node &t)const{
        return f[idx]<t.f[idx];
    }
}data[maxn],kd[maxn<<2];
int flag[maxn<<2];
pair<ll,node> res;
void build(int l,int r,int rt,int dept)
{
    if(l>r)return;
    flag[rt]=1;
    flag[rt<<1]=flag[rt<<1|1]=-1;
    idx=dept%2;
    int mid=(l+r)>>1;
    nth_element(data+l,data+mid,data+r+1);
    kd[rt]=data[mid];
    build(l,mid-1,rt<<1,dept+1);
    build(mid+1,r,rt<<1|1,dept+1);
}
inline ll getDis(int rt,node p) //求距离
{
    return (ll)Sqrt((ll)p.f[0]-kd[rt].f[0])+(ll)Sqrt((ll)p.f[1]-kd[rt].f[1]);
}
void query(node p,int rt,int dept)
{
    if(flag[rt]==-1)return;
    pair<ll,node> cur{getDis(rt,p),kd[rt]};
    int idm=dept%2;
    bool fg=false;
    int x=rt<<1;
    int y=rt<<1|1;
    if(p.f[idm]>=kd[rt].f[idm]){
        swap(x,y);
    }
    if(~flag[x]){
        query(p,x,dept+1);
    }
    if(res.fir==-1){ //取第一个
        if(cur.sec.f[2]<=p.f[2]){
            res.fir=cur.fir,res.sec=cur.sec;
        }
        fg=true;
    }
    else{
        if(cur.sec.f[2]<=p.f[2]&&(cur.fir<res.fir||(cur.fir==res.fir&&cur.sec.id<res.sec.id))){
            res.fir=cur.fir,res.sec=cur.sec;
        }
        if((ll)Sqrt(kd[rt].f[idm]-p.f[idm])<res.fir){
            fg=true;
        }
    }
    if(~flag[y]&&fg){
        query(p,y,dept+1);
    }
}
int main()
{
  // fin;
    int t,n,m;
    t=read();
    while(t--){
        n=read(),m=read();
        for(int i=0;i<n;++i){
            for(int j=0;j<3;++j){
                data[i].f[j]=read();
            }
            data[i].id=i;
        }
        build(0,n-1,1,0);
        while(m--){
            node p;
            for(int i=0;i<3;++i){
                p.f[i]=read();
            }
            res.fir=-1;
            query(p,1,0);
            printf("%d %d %d\n",res.sec.f[0],res.sec.f[1],res.sec.f[2]);
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值