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亚洲区青岛站-重现赛(感谢中国石油大学)

【题目链接】:http://acm.split.hdu.edu.cn/showproblem.php?pid=5992

【题解】



先炫耀一下;



kd-tree;

如果没学过kd-tree不建议你再往下看。

这里不能用那个四边形的估价函数;会超时。

有一个更好的估价函数是

judge=(op.d[fx]-t[rt].d[fx])^2;

op是输入的询问,d[2]表示坐标;(二维)

这里的fx是kd-tree中当前这个域的划分依据,fx==0表示是以x轴作为划分依据、fx==1表示是以y轴作为划分依据;

具体点

    int zuo = t[rt].l,you = t[rt].r;
if (op.d[fx]>t[rt].d[fx])//先搞fx维坐标离操作坐标近的;
swap(zuo,you);
query(zuo,1-fx);//优先搞"左"子树
bool should = false;//判断要不要搞右子树;
if (dis == INF)//如果距离为正无穷表示还没有更新过答案就要搞
should = true;
else
{
LL ju = sqr(op.d[fx]-t[rt].d[fx]);//否则看看这个划分依据fx的维当前这个fx坐标与操作坐标的距离的平方
//经过了swap "you"子树内全部都是比t[rt].d[fx]小或全都比它大的节点;
if (ju <= dis)//如果估价函数比当前更新到的答案小;那么就要搞右子树
should = true;//如果估价函数比当前更新到的答案还要大,那么就不要搞右子树了;
}//因为如果继续搞右子树,fx这一维的坐标在右子树里面是单调的;ju只会越来越大;
if (should)
query(you,1-fx);

除此之外;还可以在每个树的节点里面储存以这个节点为根的子树下面最低消费最小的min;如果min都大于op.n则可以不用进入子树了;

(交程序的时候选g++不然会莫名TLE);



【完整代码】

#include <cstdio>
#include <algorithm>
#define LL long long using namespace std; const int MAXN = 205000;
const LL INF = 1e18; struct point
{
int min, n, dot, l,r;
LL d[2];
}; int n, m, root, now;
LL dis; point t[MAXN];
point op,ans; void input_data()
{
scanf("%d%d", &n,&m);
for (int i = 1; i <= n; i++)
{
scanf("%I64d%I64d%d", &t[i].d[0], &t[i].d[1],&t[i].n);
t[i].dot = i;
}
} bool cmp_1(point a, point b)
{
return a.d[now] < b.d[now];
} void gengxin(int father, int son)
{
if (t[father].min > t[son].min)
t[father].min = t[son].min;
} void up_data(int rt)
{
t[rt].min = t[rt].n;
int l = t[rt].l, r = t[rt].r;
if (l) gengxin(rt, l);
if (r) gengxin(rt, r);
} int build(int begin, int end, int fa,int fx)
{
int m = (begin + end) >> 1;
now = fx;
nth_element(t + begin, t + m, t + end + 1, cmp_1);
if (begin < m)
t[m].l = build(begin, m - 1, m, 1 - fx);
else
t[m].l = 0;
if (m < end)
t[m].r = build(m + 1, end, m, 1 - fx);
else
t[m].r = 0;
up_data(m);
return m;
} LL sqr(LL x)
{
return x*x;
} void query(int rt,int fx)
{
if (!rt)
return;
int temp1 = t[rt].min;
if (temp1 > op.n)
return;
if (t[rt].n <= op.n)
{
LL dd = sqr(op.d[0]-t[rt].d[0])+sqr(op.d[1]-t[rt].d[1]);
if (dd < dis || (dd==dis && t[rt].dot < ans.dot))
{
dis = dd;
ans.d[0] = t[rt].d[0];
ans.d[1] = t[rt].d[1];
ans.n = t[rt].n;
ans.dot = t[rt].dot;
}
}
int zuo = t[rt].l,you = t[rt].r;
if (op.d[fx]>t[rt].d[fx])
swap(zuo,you);
query(zuo,1-fx);
bool should = false;
if (dis == INF)
should = true;
else
{
LL ju = sqr(op.d[fx]-t[rt].d[fx]);
if (ju <= dis)
should = true;
}
if (should)
query(you,1-fx);
} void get_ans()
{
root = build(1, n, 0, 0);
for (int i = 1; i <= m; i++)
{
scanf("%I64d%I64d%d",&op.d[0],&op.d[1],&op.n);
dis = INF;
query(root,0);
printf("%I64d %I64d %d\n",ans.d[0],ans.d[1],ans.n);
}
} int main()
{
//freopen("F:\\rush.txt","r",stdin);
int T;
scanf("%d",&T);
while (T--)
{
input_data();
get_ans();
}
return 0;
}

【22.95%】【hdu 5992】Finding Hotels的更多相关文章

  1. 【改革春风吹满地 HDU - 2036 】【计算几何-----利用叉积计算多边形的面积】

    利用叉积计算多边形的面积 我们都知道计算三角形的面积时可以用两个邻边对应向量积(叉积)的绝对值的一半表示,那么同样,对于多边形,我们可以以多边形上的一个点为源点,作过该点并且过多边形其他点中的某一个的 ...

  2. 【HDU 5145】 NPY and girls(组合+莫队)

    pid=5145">[HDU 5145] NPY and girls(组合+莫队) NPY and girls Time Limit: 8000/4000 MS (Java/Other ...

  3. Least Common Multiple (HDU - 1019) 【简单数论】【LCM】【欧几里得辗转相除法】

    Least Common Multiple (HDU - 1019) [简单数论][LCM][欧几里得辗转相除法] 标签: 入门讲座题解 数论 题目描述 The least common multip ...

  4. 七夕节 (HDU - 1215) 【简单数论】【找因数】

    七夕节 (HDU - 1215) [简单数论][找因数] 标签: 入门讲座题解 数论 题目描述 七夕节那天,月老来到数字王国,他在城门上贴了一张告示,并且和数字王国的人们说:"你们想知道你们 ...

  5. 【HDU 2255】奔小康赚大钱 (最佳二分匹配KM算法)

    奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  6. 【二分】【最长上升子序列】HDU 5489 Removed Interval (2015 ACM/ICPC Asia Regional Hefei Online)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5489 题目大意: 一个N(N<=100000)个数的序列,要从中去掉相邻的L个数(去掉整个区间 ...

  7. 【贪心】【模拟】HDU 5491 The Next (2015 ACM/ICPC Asia Regional Hefei Online)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5491 题目大意: 一个数D(0<=D<231),求比D大的第一个满足:二进制下1个个数在 ...

  8. 【动态规划】【二分】【最长上升子序列】HDU 5773 The All-purpose Zero

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5773 题目大意: T组数据,n个数(n<=100000),求最长上升子序列长度(0可以替代任何 ...

  9. 【动态规划】【KMP】HDU 5763 Another Meaning

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5763 题目大意: T组数据,给两个字符串s1,s2(len<=100000),s2可以被解读成 ...

随机推荐

  1. java(内部类)

    内部类: 一个类定义在另外一个类的内部就称作为内部类. 内部类的类别: 1.成员内部类: 2.局部内部类: 1.成员内部类: 成员内部类的访问方式: 方式一:在成员内部类的外侧提供一个方法创建内部类的 ...

  2. deep-in-es6(七)

    Symbols对象 JavaScript的第七种原始类型 以前的数据类型: Undefined 未定义 Null 空值 Boolean 布尔类型 Number 数字类型 String 字符串类型 Ob ...

  3. vue 遇到的报错

    [Vue warn]: Invalid default value for prop "dataParams": Props with type Object/Array must ...

  4. Spring模块作用

    0.模块整理 Spring模块整理(http://www.kuqin.com/shuoit/20150805/347434.html) 模块名 作用 资料 aop  spring的面向切面编程,提供A ...

  5. 我的第一个Django项目

    1.创建Django项目 命令:django-admin startproject 项目名 注意:创建应用必须先进入虚拟环境. 项目目录如下: 目录层级说明: __init__.py: 说明demo0 ...

  6. Linux-PS1变量详解

    1.PS1 要修改linux终端命令行颜色,我们需要用到PS1,PS1是Linux终端用户的一个环境变量,用来说明命令行提示符的设置.在终端输入命令:#set,即可在输出中找到关于PS1的定义如下: ...

  7. syslog日志介绍

    一. syslog简介 syslog是一种工业标准的协议,可用来记录设备的日志.在UNIX系统,路由器.交换机等网络设备中,系统日志(System Log)记录系统中任何时间发生的大小事件.管理者可以 ...

  8. git -处理分支合并

    1.分支间的合并 1)直接合并:把两个分支上的历史轨迹合二为一(就是所以修改都全部合并) zhangshuli@zhangshuli-MS-:~/myGit$ vim merge.txt zhangs ...

  9. [NOI.AC#35]string 缩点+拓扑排序

    链接 因为有交换相邻字母,因此给你字符串就相当于给你了这个字符串的所有排列 把等价的串映射到整数范围,再根据 \(m\) 种魔法连边,缩点后在 DAG 上DP即可 无耻地用了int128 #inclu ...

  10. mysql 造1亿条记录的单表--大数据表

    读写文件 背景及木:现有数据1000w单表,为压力测试准备1亿条数据. 步骤: 1.将1000w条记录,除id外都导入到多个文件中: //DELIMITER DROP PROCEDURE if EXI ...