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 ...
随机推荐
- wxwidgets编译及环境配置
wxwidgets编译及环境配置 安装步骤: 到www.CodeBlocks.org下载并安装CodeBlocks,最好下载MinGW版本的,可以省掉安装和配置GCC的麻烦. 到www.wxWidge ...
- Delphi与JAVA互加解密AES算法
搞了半天终于把这个对应的参数搞上了,话不多说,先干上代码: package com.bss.util; import java.io.UnsupportedEncodingException; imp ...
- Bootstrap 网格系统(Grid System)实例3
Bootstrap 网格系统(Grid System)实例:堆叠水平 <!DOCTYPE html><html><head><meta http-equiv= ...
- mysql 复制中的 paxso 的两阶段和事务两阶段的区别
1.普通的两阶段是 推送不同的数据给不同的主机,一旦出现网络中断,造成问题是不可服务. 因为本身有锁,故无所谓. 2.paxos 的两阶段是将相同的 数据给不同的主机,一旦超过半数即可认为成功.
- httpClient类
@SuppressWarnings("finally") public JSONObject doPost(String url, String parms){ if (" ...
- Hanoi双塔问题
题目描述: 给定A.B.C三根足够长的细柱,在A柱上放有2n个中间有孔的圆盘,共有n个不同的尺寸,每个尺寸都有两个相同的圆盘,注意这两个圆盘是不加区分的(下图为n=3的情形).现要将这些圆盘移到C柱上 ...
- (33)zabbix proxy分布式监控配置
概述 zabbix proxy可以代替zabbix server检索客户端的数据,然后把数据汇报给zabbix server,并且在一定程度上分担了zabbix server的压力.zabbix pr ...
- GIMP永久保存选择的办法
选择选区,然后把选区放到channel里面去 这是一张已经选择好的选区的图片 然后选择select下的Save to Channel, 需要这部分选区的话,只需要点击这个按钮就可以了
- mbist summary
1. 关于mbist,网上也有介绍,觉得不错: 推荐的mbistt的博客:奋斗的猪 2.使用的工具是mbistarchitect,不是tessent. 3.工具使用的相关文档:从EETOP和工具自带的 ...
- go 和make的用法 区别
Doand Make are two verbs which frequently confuse students of English. Learn the Difference between ...