The Closest M Points BZOJ 3053
The Closest M Points
【问题描述】
软工学院的课程很讨厌!ZLC同志遇到了一个头疼的问题:在K维空间里面有许多的点,对于某些给定的点,ZLC需要找到和它最近的m个点。
(这里的距离指的是欧几里得距离:D(p, q) = D(q, p) = sqrt((q1 - p1) ^ 2 + (q2 - p2) ^ 2 + (q3 - p3) ^ 2 + ... + (qn - pn) ^ 2)
ZLC要去打Dota,所以就麻烦你帮忙解决一下了……
【输入格式】
第一行,两个非负整数:点数n(1 <= n <= 50000),和维度数k(1 <= k <= 5)。
接下来的n行,每行k个整数,代表一个点的坐标。
接下来一个正整数:给定的询问数量t(1 <= t <= 10000)
下面2*t行:
第一行,k个整数:给定点的坐标
第二行:查询最近的m个点(1 <= m <= 10)
所有坐标的绝对值不超过10000。
有多组数据!
【输出格式】
对于每个询问,输出m+1行:
第一行:"the closest m points are:" m为查询中的m
接下来m行每行代表一个点,按照从近到远排序。
保证方案唯一,下面这种情况不会出现:
2 2
1 1
3 3
1
2 2
1
【样例输入】
3 2
1 1
1 3
3 4
2
2 3
2
2 3
1
【样例输出】
5
0
4
题解:
题意就是求与给定点第一近到第m近的点
用KD树查询
期望答案的计算:与给定点最近且不与给定点在同一块的期望点必定在边界上
开始时先将m个inf加入
那么当查询到的点与给定点的距离小于堆顶与给定点的距离时,就去掉堆顶并加入这个点
最后倒序输出
注意初始化(虽然没写什么初始化,但是要考虑一下的)
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
inline void Scan(int &x)
{
int o = ;
char c;
while((c = getchar()) < '' || c > '')
if(c == '-') o = -;
x = c - '';
while((c = getchar()) >= '' && c <= '') x = x * + c - '';
x *= o;
}
const int me = ;
const int inf = ;
struct dot
{
int lc, rc;
int dis;
int v[], mi[], ma[];
};
dot point;
dot c[me];
dot tr[me];
dot ans[me];
struct name
{
int x;
int dis;
};
inline bool operator < (const name &a, const name &b)
{
return a.dis < b.dis;
}
priority_queue <name> sta;
int e, n, k, m;
inline bool cmp(const dot &a, const dot &b)
{
return a.v[e] < b.v[e];
}
inline int Min(const int &x, const int &y)
{
return (x < y) ? x : y;
}
inline int Max(const int &x, const int &y)
{
return (x > y) ? x : y;
}
inline int Sqr(const int &x)
{
return x * x;
}
inline void Update(const int &x)
{
int l = tr[x].lc, r = tr[x].rc;
for(int i = ; i < k; ++i)
{
tr[x].mi[i] = tr[x].ma[i] = tr[x].v[i];
if(l) tr[x].mi[i] = Min(tr[x].mi[i], tr[l].mi[i]), tr[x].ma[i] = Max(tr[x].ma[i], tr[l].ma[i]);
if(r) tr[x].mi[i] = Min(tr[x].mi[i], tr[r].mi[i]), tr[x].ma[i] = Max(tr[x].ma[i], tr[r].ma[i]);
}
}
int Build(const int &l, const int &r, int d)
{
if(d >= k) d -= k;
e = d;
int mi = l + r >> ;
nth_element(c + l, c + mi, c + r + , cmp);
tr[mi] = c[mi];
if(l < mi) tr[mi].lc = Build(l, mi - , d + );
if(r > mi) tr[mi].rc = Build(mi + , r, d + );
Update(mi);
return mi;
}
inline int Dis(const int &x)
{
int sum = ;
for(int i = ; i < k; ++i)
sum += Sqr(tr[x].v[i] - point.v[i]);
return sum;
}
inline int Get(const int &x)
{
int sum = ;
for(int i = ; i < k; ++i)
{
if(point.v[i] < tr[x].mi[i]) sum += Sqr(tr[x].mi[i] - point.v[i]);
if(point.v[i] > tr[x].ma[i]) sum += Sqr(point.v[i] - tr[x].ma[i]);
}
return sum;
}
void Ask(const int &x)
{
int dis = Dis(x);
if(dis < sta.top().dis)
{
sta.pop();
sta.push((name) {x, dis});
}
int le = inf, ri = inf;
if(tr[x].lc) le = Get(tr[x].lc);
if(tr[x].rc) ri = Get(tr[x].rc);
if(le < ri)
{
if(le < sta.top().dis) Ask(tr[x].lc);
if(ri < sta.top().dis) Ask(tr[x].rc);
}
else
{
if(ri < sta.top().dis) Ask(tr[x].rc);
if(le < sta.top().dis) Ask(tr[x].lc);
}
}
int main()
{
// freopen("d.in", "r", stdin), freopen("d.out", "w", stdout);
while(~scanf("%d", &n))
{
Scan(k);
for(int i = ; i <= n; ++i)
for(int j = ; j < k; ++j)
Scan(c[i].v[j]);
int root = Build(, n, );
int t;
Scan(t);
while(t--)
{
for(int i = ; i < k; ++i) Scan(point.v[i]);
Scan(m);
for(int i = ; i <= m; ++i) sta.push((name) {, inf});
Ask(root);
for(int i = ; i <= m; ++i)
{
ans[i] = tr[sta.top().x];
sta.pop();
}
printf("the closest %d points are:\n", m);
for(int i = m; i >= ; --i)
{
for(int j = ; j < k - ; ++j)
printf("%d ", ans[i].v[j]);
printf("%d\n", ans[i].v[k - ]);
}
}
}
}
The Closest M Points BZOJ 3053的更多相关文章
- bzoj 3053 HDU 4347 : The Closest M Points kd树
bzoj 3053 HDU 4347 : The Closest M Points kd树 题目大意:求k维空间内某点的前k近的点. 就是一般的kd树,根据实测发现,kd树的两种建树方式,即按照方差 ...
- 【BZOJ】【3053】The Closest M Points
KD-Tree 题目大意:K维空间内,与给定点欧几里得距离最近的 m 个点. KD树啊……还能怎样啊……然而扩展到k维其实并没多么复杂?除了我已经脑补不出建树过程……不过代码好像变化不大>_&g ...
- 【BZOJ】3053: The Closest M Points(kdtree)
http://www.lydsy.com/JudgeOnline/problem.php?id=3053 本来是1a的QAQ.... 没看到有多组数据啊.....斯巴达!!!!!!!!!!!!!!!! ...
- 【BZOJ 3053】The Closest M Points
KDTree模板,在m维空间中找最近的k个点,用的是欧几里德距离. 理解了好久,昨晚始终不明白那些“估价函数”,后来才知道分情况讨论,≤k还是=k,在当前这一维度距离过线还是不过线,过线则要继续搜索另 ...
- BZOJ 3053 The Closest M Points
[题目分析] 典型的KD-Tree例题,求k维空间中的最近点对,只需要在判断的过程中加上一个优先队列,就可以了. [代码] #include <cstdio> #include <c ...
- BZOJ 3053: The Closest M Points(K-D Tree)
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1235 Solved: 418[Submit][Status][Discuss] Descripti ...
- bzoj 3053: The Closest M Points【KD-tree】
多维KDtree板子 左右儿子的估价用mn~mx当区间,假设区间里的数都存在:k维轮着做割点 #include<iostream> #include<cstdio> #incl ...
- 【kd-tree】bzoj3053 The Closest M Points
同p2626.由于K比较小,所以不必用堆. #include<cstdio> #include<cstring> #include<cmath> #include& ...
- 【HDOJ】4347 The Closest M Points
居然是KD解. /* 4347 */ #include <iostream> #include <sstream> #include <string> #inclu ...
随机推荐
- leetcode_1052. Grumpy Bookstore Owner
1052. Grumpy Bookstore Owner https://leetcode.com/problems/grumpy-bookstore-owner/ 题意:每个时刻i会有custome ...
- Java——舞动的排序
一.冒泡排序: http://v.youku.com/v_show/id_XMzMyOTAyMzQ0.html //冒泡排序 public class Bubbling { public static ...
- qemu-img管理虚拟机
qemu-img管理虚拟机 1. 查看正在运行的虚拟机 [root@idca-vm02 ~]# virsh list Id 名称 状态 ----- ...
- ios 团购信息客户端demo(三)
接上二篇的内容,今天我们就来介绍一下如何将解析出来的数据放入AQGridView中显示出来,因为我们的工程中已经将AQGridView导入了,所以我们在KKFirstViewController中直接 ...
- SVN的使用二
一,打开SCM 在xcode中,点击菜单: File -> Source Control –> Repositories 二,连接SVN服务器 1, 2,配置SVN服务器地址(http:/ ...
- python中enumerate()函数的用法
描述: enumerate() 函数用于将一个可遍历的数据对象(如列表.元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中.其英文意为:枚举,列举. 函数说明: 语法 ...
- (13)zabbix External checks 外部命令检测
1. 概述 zabbix server运行脚本或者二进制文件来执行外部检测,外部检测不需要在被监控端运行任何agentd item key语法如下: ARGUMENT DEFINITION scri ...
- 无法解析具体reference那个同名文件
公司平台,如果src和gen文件系统中有同名文件.reference时会根据depend.cfg文件优先reference遇到的同名文件.这样如果存在同名文件且引用顺序不对就会有莫名的bug. 像rt ...
- python-小数据池,再谈编码,is和 == 的区别
一 . 小数据池 # 小数据池针对的是: int, str, bool 在py文件中几乎所有的字符串都会缓存. # id() 查看变量的内存地址 s = 'attila' print(id(s)) 二 ...
- solr DIH 设置定时索引
1 web.xml中加入 web.xml所在目录 /opt/solr-7.7.1/server/solr-webapp/webapp/WEB-INF <listener> <list ...