题意:n家旅店,每个旅店都有坐标x,y,每晚价钱z,m个客人,坐标x,y,钱c,问你每个客人最近且能住进去(非花最少钱)的旅店,一样近的选排名靠前的。

思路:KD树模板题

代码:

#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
typedef long long ll;
const int maxn = + ;
const int seed = ;
const ll MOD = 1e9 + ;
const int INF = 0x3f3f3f3f;
using namespace std; #define lson rt << 1
#define rson rt << 1 | 1
#define Pair pair<ll, Node> int k, idx; //维数k struct Node
{
int feature[]; //定义属性数组
int id;
bool operator < (const Node &u) const
{
return feature[idx] < u.feature[idx];
}
}_data[maxn], p; //_data[]数组代表输入的数据
Node data[ * maxn]; //data[]数组代表K-D树的所有节点数据
int flag[ * maxn]; //用于标记某个节点是否存在,1表示存在,-1表示不存在 priority_queue<Pair> Q; //队列Q用于存放离p最近的m个数据
ll Sqrt(ll a, ll b){ //欧几里得距离平方
return (a - b) * 1LL * (a - b);
} //建树步骤,参数dept代表树的深度
void Build(int l, int r, int rt, int dept)
{
if(l > r) return;
flag[rt] = ; //表示编号为rt的节点存在
flag[lson] = flag[rson] = -; //当前节点的孩子暂时标记不存在
idx = dept % k; //按照编号为idx的属性进行划分
int mid = (l + r) >> ;
nth_element(_data + l, _data + mid, _data + r + ); //nth_element()为STL中的函数 algorithm
data[rt] = _data[mid];
Build(l, mid - , lson, dept + ); //递归左子树
Build(mid + , r, rson, dept + ); //递归右子树
} //查询函数,寻找离p最近的m个特征属性
void Query(Node p, int m, int rt, int dept)
{
if(flag[rt] == -) return; //不存在的节点不遍历
Pair cur(, data[rt]); //获取当前节点的数据和到p的距离
for(int i = ; i < k; i++) //欧几里得距离的平方
cur.first += Sqrt((ll)data[rt].feature[i], (ll)p.feature[i]);
int dim = dept % k; //跟建树一样,这样能保证相同节点的dim值不变
bool fg = ; //用于标记是否需要遍历右子树
int x = lson;
int y = rson;
if(p.feature[dim] >= data[rt].feature[dim]) //数据p的第dim个特征值大于等于当前的数据,则需要进入右子树
swap(x, y);
if(~flag[x]) Query(p, m, x, dept + ); //如果节点x存在,则进入子树继续遍历 //以下是回溯过程,维护一个优先队列
if(Q.size() < m) //如果队列没有满,则继续放入
{
if(cur.second.feature[] <= p.feature[]) Q.push(cur);
fg = ;
}
else
{
if(cur.first < Q.top().first && cur.second.feature[] <= p.feature[]) //如果找到更小的距离,则用于替换队列Q中最大的距离的数据
{
Q.pop();
Q.push(cur);
}
else if(cur.first == Q.top().first && cur.second.id < Q.top().second.id && cur.second.feature[] <= p.feature[]){
Q.pop();
Q.push(cur);
}
if(Sqrt((ll)p.feature[dim], (ll)data[rt].feature[dim]) < Q.top().first)
{
fg = ;
}
}
if(~flag[y] && fg)
Query(p, m, y, dept + );
}
int main(){
int T, n, m;
k = ;
scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &m);
for(int i = ; i < n; i++){
for(int j = ; j < ; j++)
scanf("%d", &_data[i].feature[j]);
_data[i].id = i;
}
Build(, n - , , );
while(m--){
while(!Q.empty()) Q.pop();
for(int i = ; i < ; i++)
scanf("%d", &p.feature[i]);
Query(p, , , );
p = Q.top().second;
printf("%d %d %d\n", p.feature[], p.feature[], p.feature[]);
}
}
return ;
}

模板:

#define lson rt << 1
#define rson rt << 1 | 1
#define Pair pair<ll, Node> int k, idx; //维数k struct Node
{
int feature[]; //定义属性数组
int id;
bool operator < (const Node &u) const
{
return feature[idx] < u.feature[idx];
}
}_data[maxn], p; //_data[]数组代表输入的数据
Node data[ * maxn]; //data[]数组代表K-D树的所有节点数据
int flag[ * maxn]; //用于标记某个节点是否存在,1表示存在,-1表示不存在 priority_queue<Pair> Q; //队列Q用于存放离p最近的m个数据
ll Sqrt(ll a, ll b){ //欧几里得距离平方
return (a - b) * 1LL * (a - b);
} //建树步骤,参数dept代表树的深度
void Build(int l, int r, int rt, int dept)
{
if(l > r) return;
flag[rt] = ; //表示编号为rt的节点存在
flag[lson] = flag[rson] = -; //当前节点的孩子暂时标记不存在
idx = dept % k; //按照编号为idx的属性进行划分
int mid = (l + r) >> ;
nth_element(_data + l, _data + mid, _data + r + ); //nth_element()为STL中的函数 algorithm
data[rt] = _data[mid];
Build(l, mid - , lson, dept + ); //递归左子树
Build(mid + , r, rson, dept + ); //递归右子树
} //查询函数,寻找离p最近的m个特征属性
void Query(Node p, int m, int rt, int dept)
{
if(flag[rt] == -) return; //不存在的节点不遍历
Pair cur(, data[rt]); //获取当前节点的数据和到p的距离
for(int i = ; i < k; i++) //欧几里得距离的平方
cur.first += Sqrt((ll)data[rt].feature[i], (ll)p.feature[i]);
int dim = dept % k; //跟建树一样,这样能保证相同节点的dim值不变
bool fg = ; //用于标记是否需要遍历右子树
int x = lson;
int y = rson;
if(p.feature[dim] >= data[rt].feature[dim]) //数据p的第dim个特征值大于等于当前的数据,则需要进入右子树
swap(x, y);
if(~flag[x]) Query(p, m, x, dept + ); //如果节点x存在,则进入子树继续遍历 if(Q.size() < m) //如果队列没有满,则继续放入
{ //注意,这里必须让fg=1,以后改时注意
Q.push(cur);
fg = ;
}
else
{
if(cur.first < Q.top().first) //如果找到更小的距离,则用于替换队列Q中最大的距离的数据
{
Q.pop();
Q.push(cur);
}
if(Sqrt((ll)p.feature[dim], (ll)data[rt].feature[dim]) < Q.top().first)
{
fg = ;
}
}
if(~flag[y] && fg)
Query(p, m, y, dept + );
}

HDU 5992 Finding Hotels(KD树)题解的更多相关文章

  1. HDU 5809 Ants(KD树+并查集)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5809 [题目大意] 给出一些蚂蚁和他们的巢穴,一开始他们会在自己的巢穴(以二维坐标形式给出),之后 ...

  2. K-D树问题 HDU 4347

    K-D树可以看看这个博客写的真心不错!这里存个版 http://blog.csdn.net/zhjchengfeng5/article/details/7855241 HDU 4349 #includ ...

  3. 2016 ICPC青岛站---k题 Finding Hotels(K-D树)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5992 Problem Description There are N hotels all over ...

  4. 【HDU5992】Finding Hotels 【KD树】

    题意 给出n个酒店的坐标和价格,然后m个查询,每个查询给出一个人的坐标和能承受的最大价格,然后找出在他价格承受范围以内,距离他最近的宾馆,如果有多个,那么输出第一个 分析 kd树的模板题 #inclu ...

  5. bzoj 3053 HDU 4347 : The Closest M Points kd树

    bzoj 3053 HDU 4347 : The Closest M Points  kd树 题目大意:求k维空间内某点的前k近的点. 就是一般的kd树,根据实测发现,kd树的两种建树方式,即按照方差 ...

  6. HDU 6022---MG loves set(K-D树)

    题目链接 Problem Description MG is an intelligent boy. One day he was challenged by the famous master ca ...

  7. hdu 4347 The Closest M Points (kd树)

    版权声明:本文为博主原创文章,未经博主允许不得转载. hdu 4347 题意: 求k维空间中离所给点最近的m个点,并按顺序输出  . 解法: kd树模板题 . 不懂kd树的可以先看看这个 . 不多说, ...

  8. 数据结构(KD树):HDU 4347 The Closest M Points

    The Closest M Points Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 98304/98304 K (Java/Ot ...

  9. hdu 2966 In case of failure k-d树

    题目链接 给n个点, 求出每个点到离它最近的点的距离. 直接建k-d树然后查询就可以  感觉十分神奇... 明白了算法原理但是感觉代码还不是很懂... #include <bits/stdc++ ...

随机推荐

  1. 配置tomcat通过客户端访问

    1:在tomcat    conf/tomcat-users.xml 文件里  配置用户名和密码,以及访问方式 For example, to add the manager-gui role to ...

  2. em和px比较

    1em=16px. em具有继承性. 如果定义了 body{font-size=12px;} #title{font-siez=2.6em;} 而id=title恰好在body里面,那么,id=tit ...

  3. Fiddler抓包域名过滤

    Fiddler抓包域名过滤 我们在用Fiddler抓包的时候会抓到很多不需要的数据包,我们怎样才能过滤掉不想要的域名只显示自己想要的域名? 通过Fiddler域名过滤可以解决这一问题! 下面是只显示想 ...

  4. Look for the Air Jordan 32 in full family sizing

    Following the release of the 'Rosso Corsa' colorway, Jordan Brand is now set to officially launch th ...

  5. shell基础:1.0概述

    解释型.不用编译. 主要有两个工能:1.命令解释器 2.编程

  6. linux命令:压缩解压命令

    压缩解压命令:gzip 命令名称:gzip 命令英文原意:GNU zip 命令所在路径:/bin/gzip 执行权限:所有用户 语法:gzip 选项  [文件] 功能描述:压缩文件 压缩后文件格式:g ...

  7. 001-Two Sum

    Given an array of integers, return indices of the two numbers such that they add up to a specific ta ...

  8. Java有序数组的实现

    package 有序数组; public class OrdArray { private long[]array; private int nElems; //初始化 public OrdArray ...

  9. ts实战项目启动中遇到的问题

    项目链接:https://github.com/Jiasm/typescript-example 储备知识须知: sequelize入门篇 : 依照README执行以下操作: npm i brew s ...

  10. distinct count

    实验:查询一个column的无重复记录,需要知道有多少条记录,并显示记录. 统计记录用count(*)函数,无重复记录distinct,以emp表为例. (1)先查询无重复记录 [@more@] SQ ...