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的更多相关文章

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

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

  2. 【BZOJ】【3053】The Closest M Points

    KD-Tree 题目大意:K维空间内,与给定点欧几里得距离最近的 m 个点. KD树啊……还能怎样啊……然而扩展到k维其实并没多么复杂?除了我已经脑补不出建树过程……不过代码好像变化不大>_&g ...

  3. 【BZOJ】3053: The Closest M Points(kdtree)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3053 本来是1a的QAQ.... 没看到有多组数据啊.....斯巴达!!!!!!!!!!!!!!!! ...

  4. 【BZOJ 3053】The Closest M Points

    KDTree模板,在m维空间中找最近的k个点,用的是欧几里德距离. 理解了好久,昨晚始终不明白那些“估价函数”,后来才知道分情况讨论,≤k还是=k,在当前这一维度距离过线还是不过线,过线则要继续搜索另 ...

  5. BZOJ 3053 The Closest M Points

    [题目分析] 典型的KD-Tree例题,求k维空间中的最近点对,只需要在判断的过程中加上一个优先队列,就可以了. [代码] #include <cstdio> #include <c ...

  6. BZOJ 3053: The Closest M Points(K-D Tree)

    Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1235  Solved: 418[Submit][Status][Discuss] Descripti ...

  7. bzoj 3053: The Closest M Points【KD-tree】

    多维KDtree板子 左右儿子的估价用mn~mx当区间,假设区间里的数都存在:k维轮着做割点 #include<iostream> #include<cstdio> #incl ...

  8. 【kd-tree】bzoj3053 The Closest M Points

    同p2626.由于K比较小,所以不必用堆. #include<cstdio> #include<cstring> #include<cmath> #include& ...

  9. 【HDOJ】4347 The Closest M Points

    居然是KD解. /* 4347 */ #include <iostream> #include <sstream> #include <string> #inclu ...

随机推荐

  1. wxwidgets编译及环境配置

    wxwidgets编译及环境配置 安装步骤: 到www.CodeBlocks.org下载并安装CodeBlocks,最好下载MinGW版本的,可以省掉安装和配置GCC的麻烦. 到www.wxWidge ...

  2. Delphi与JAVA互加解密AES算法

    搞了半天终于把这个对应的参数搞上了,话不多说,先干上代码: package com.bss.util; import java.io.UnsupportedEncodingException; imp ...

  3. Bootstrap 网格系统(Grid System)实例3

    Bootstrap 网格系统(Grid System)实例:堆叠水平 <!DOCTYPE html><html><head><meta http-equiv= ...

  4. mysql 复制中的 paxso 的两阶段和事务两阶段的区别

    1.普通的两阶段是 推送不同的数据给不同的主机,一旦出现网络中断,造成问题是不可服务. 因为本身有锁,故无所谓. 2.paxos 的两阶段是将相同的 数据给不同的主机,一旦超过半数即可认为成功.

  5. httpClient类

    @SuppressWarnings("finally") public JSONObject doPost(String url, String parms){ if (" ...

  6. Hanoi双塔问题

    题目描述: 给定A.B.C三根足够长的细柱,在A柱上放有2n个中间有孔的圆盘,共有n个不同的尺寸,每个尺寸都有两个相同的圆盘,注意这两个圆盘是不加区分的(下图为n=3的情形).现要将这些圆盘移到C柱上 ...

  7. (33)zabbix proxy分布式监控配置

    概述 zabbix proxy可以代替zabbix server检索客户端的数据,然后把数据汇报给zabbix server,并且在一定程度上分担了zabbix server的压力.zabbix pr ...

  8. GIMP永久保存选择的办法

    选择选区,然后把选区放到channel里面去 这是一张已经选择好的选区的图片 然后选择select下的Save to Channel, 需要这部分选区的话,只需要点击这个按钮就可以了

  9. mbist summary

    1. 关于mbist,网上也有介绍,觉得不错: 推荐的mbistt的博客:奋斗的猪 2.使用的工具是mbistarchitect,不是tessent. 3.工具使用的相关文档:从EETOP和工具自带的 ...

  10. go 和make的用法 区别

    Doand Make are two verbs which frequently confuse students of English. Learn the Difference between ...