本文参考:

https://www.cnblogs.com/GerynOhenz/p/8727415.html

kuangbin的ACM模板(新)


题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4347

Problem Description

The course of Software Design and Development Practice is objectionable. ZLC is facing a serious problem .There are many points in K-dimensional space .Given a point. ZLC need to find out the closest m

points. Euclidean distance is used as the distance metric between two points. The Euclidean distance between points p and q is the length of the line segment connecting them.In Cartesian coordinates, if p =

(p1, p2,..., pn) and q = (q1, q2,..., qn) are two points in Euclidean n-space, then the distance from p to q, or from q to p is given by:

$d\left( {{\bf{p}},{\bf{q}}} \right) = d\left( {{\bf{q}},{\bf{p}}} \right) = \sqrt {\sum\limits_{i = 1}^n {\left( {p_i - q_i } \right)^2 } }$

Can you help him solve this problem?

Input

In the first line of the text file. There are two non-negative integers n and K. They denote respectively: the number of points, 1 <= n <= 50000, and the number of Dimensions, 1 <= K <= 5. In each of the following n lines there is written K integers, representing the coordinates of a point. This followed by a line with one positive integer t, representing the number of queries, 1 <= t <=10000.

Each query contains two lines. The k integers in the first line represent the given point. In the second line, there is one integer m, the number of closest points you should find,1 <= m <=10. The absolute value of all the coordinates will not be more than 10000. There are multiple test cases. Process to end of file.

Output

For each query, output m+1 lines:

The first line saying :”the closest m points are:” where m is the number of the points.

The following m lines representing m points ,in accordance with the order from near to far

It is guaranteed that the answer can only be formed in one ways. The distances from the given point to all the nearest m+1 points are different. That means input like this:

2 2
1 1
3 3
1
2 2
1

will not exist.

Sample Input
3 2
1 1
1 3
3 4
2
2 3
2
2 3
1

Sample Output
the closest 2 points are:
1 3
3 4
the closest 1 points are:
1 3

题意:

给出 $n$ 个 $K$ 维的点,又给出 $t$ 个查询, 每个查询也给出一个 $K$ 维的点,要求查询 $n$ 个点中距离这个点最近的 $M$ 个点。

题解:

KDTree模板题。


以下关于KDTree的小记:

1、简介

KDTree(K-dimensional tree) 是一个支持多维空间的数据结构,主要是将空间内的点进行区域划分,快速维护有关空间点的操作,例如空间的最远(近)点对,区间搜索。

KDTree 的结构与线段树类似,只是线段树是对一维空间的操作,而 KDTree 是多维操作的,这也导致了 KDTree 的灵活性没有线段树高。

树上每个节点所维护的信息:

  1. 左右两个儿子
  2. 该点表示的空间范围(超长方体,当 $K=2$ 时为矩形,$K=3$ 时为长方体)
  3. 中位点(坐标等信息)

2.1、建树

假设我们已经有了一个描述 $K$ 维空间内的点的类Point,且我们已经有Point类型的 $a[0:n-1]$ 数组。

首先因为是空间划分,所以要循环递进地用垂直于各维度轴的超平面(或者线、平面)进行划分。

例如在二维平面上的划分,先用垂直 $x$ 轴的直线进行划分,再用垂直 $y$ 轴的直线进行划分,再用垂直 $x$ 轴的直线进行划分……

那么,假设现在要用垂直 $x$ 轴的直线划分在 $a[0:n-1]$ 数组内某个整数区间 $[l,r)$ 上的这些点,

首先初始化该点的空间范围,假设 $mid = \left\lfloor {\frac{{l + r}}{2}} \right\rfloor$,作为 $[l,r)$ 按 $x$ 坐标从小到大排序时的中位点位置,

然后用 nth_element(st,st+n,ed) 线性时间复杂度地将 $[l,r)$ 分成了  $[l,mid)$ 和 $[mid+1,r)$ 两部分,而 $a[mid]$ 则存储了中位点,

然后递归两个区间(作为左右儿子),当然,这两个区间则要用垂直 $y$ 轴的直线进行划分,以此类推。

(其中,调用 nth_element(st,st+n,ed) 方法可以求得 $[st,ed)$ 区间内所有元素中第 $n$ 小的元素,并把它放在第 $n$ 个位置上。注意,下标是从 $st+0$ 开始计数的,也就是说求第 $0$ 小的元素就是最小的数,同样地,第 $0$ 个位置是最前面的位置。)

举例:

2.2、查询 $k$ 近邻

$k$ 近邻是指找到第 $k$ 近的点,需要维护一个大顶堆,维护当前 $k$ 个点中的最远距离,如果当前点比最远距离要小,则更新大根堆,而且利用最远距离可以减掉那些不在当前第 $k$ 距离内的区间。


AC代码:

#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std; const int maxn=5e4+;
const int maxk=;
int k,idx;
struct Point
{
int x[maxk];
bool operator<(const Point &o)const
{
return x[idx]<o.x[idx];
}
void print()
{
for(int i=;i<k;i++) printf("%d%c",x[i],(i==k-)?'\n':' ');
}
}poi[maxn];
typedef pair<double,Point> P;
priority_queue<P> Q;
void clear(priority_queue<P> &Q)
{
if(Q.empty()) return;
priority_queue<P> tp;
swap(Q,tp);
}
struct kdTree
{
#define sqr(x) ((x)*(x))
#define ls (rt<<1)
#define rs (rt<<1|1)
Point o[maxn<<];
int son[maxn<<]; void build(int rt,int l,int r,int dep)
{
if(l>r) return;
son[rt]=r-l, son[ls]=son[rs]=-;
idx=dep%k;
int mid=(l+r)>>;
nth_element(poi+l,poi+mid,poi+r+);
o[rt]=poi[mid];
build(ls,l,mid-,dep+);
build(rs,mid+,r,dep+);
}
void query(int rt,Point p,int m,int dep)
{
if(son[rt]==-) return;
P nd(,o[rt]);
for(int i=;i<k;i++) nd.fi+=sqr(nd.se.x[i]-p.x[i]);
int dim=dep%k, x=ls, y=rs; bool fg=;
if(p.x[dim]>=o[rt].x[dim]) swap(x,y);
if(~son[x]) query(x,p,m,dep+);
if(Q.size()<m) Q.push(nd), fg=;
else
{
if(nd.fi<Q.top().fi) Q.pop(), Q.push(nd);
if(sqr(p.x[dim]-o[rt].x[dim])<Q.top().fi) fg=;
}
if(~son[y] && fg) query(y,p,m,dep+);
}
}kdt; int n;
int main()
{
while(cin>>n>>k)
{
for(int i=;i<n;i++) for(int j=;j<k;j++) scanf("%d",&(poi[i].x[j]));
kdt.build(,,n-,); int t; cin>>t;
stack<Point> ans;
while(t--)
{
Point qry;
for(int i=;i<k;i++) scanf("%d",&qry.x[i]);
int m; scanf("%d",&m); clear(Q);
kdt.query(,qry,m,); printf("the closest %d points are:\n",m);
while(Q.size()) ans.push(Q.top().se), Q.pop();
while(ans.size()) ans.top().print(), ans.pop();
}
}
}

HDU 4347 - The Closest M Points - [KDTree模板题]的更多相关文章

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

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

  2. hud 4347 The Closest M Points(KD-Tree)

    传送门 解题思路 \(KD-Tree\)模板题,\(KD-Tree\)解决的是多维问题,它是一个可以储存\(K\)维数据的二叉树,每一层都被一维所分割.它的插入删除复杂度为\(log^2 n\),它查 ...

  3. HDU 4347 The Closest M Points (kdTree)

    赤果果的kdTree. 学习传送门:http://www.cnblogs.com/v-July-v/archive/2012/11/20/3125419.html 其实就是二叉树的变形 #includ ...

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

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

  5. 数据结构(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 ...

  6. hdu 4347 The Closest M Points(KD树)

    Problem - 4347 一道KNN的题.直接用kd树加上一个暴力更新就撸过去了.写的时候有一个错误就是搜索一边子树的时候返回有当前层数会被改变了,然后就直接判断搜索另一边子树,搞到wa了半天. ...

  7. 洛谷 P4148 简单题 KD-Tree 模板题

    Code: //洛谷 P4148 简单题 KD-Tree 模板题 #include <cstdio> #include <algorithm> #include <cst ...

  8. hdu4347The Closest M Points kdtree

    kdtree讲解: https://blog.csdn.net/qing101hua/article/details/53228668 https://blog.csdn.net/acdreamers ...

  9. 【HDOJ】4347 The Closest M Points

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

随机推荐

  1. java webdriver的api的封装

    我们来看一下官网提供的代码写法,即最原始的写法: driver.findElement(By.id("kw")).click() 这样写是没任何问题的,但这样没有把元素对象,数据, ...

  2. ListView中的Item点击事件和子控件的冲突或者item点击没有反应的解决的方法

    fragment中加入了button和checkbox这些控件.此时这些子控件会将焦点获取到.所以经常当点击item时变化的是子控件.item本身的点击没有响应. 这时候就能够使用descendant ...

  3. Spark 论文篇-RDD:一种为内存化集群计算设计的容错抽象(中英双语)

    论文内容: 待整理 参考文献: Resilient Distributed Datasets: A Fault-Tolerant Abstraction for In-Memory Cluster C ...

  4. [svc]linux的inode和block-软硬链接

    磁盘结构 容量 磁盘结构 磁盘容量 = 一个柱面大小柱面的总数 = 磁头数量每个磁道上的扇区数一个扇区大小柱面总数 存储容量=磁头数 × 磁道(柱面)数 × 每道扇区数 × 每扇区字节数 了解-什么是 ...

  5. Java 汇编代码

    https://shipilev.net/blog/2015/black-magic-method-dispatch/ https://github.com/shipilev/article-meth ...

  6. 【Linux高级驱动】I2C驱动框架分析

    1.i2c-dev.c(i2c设备驱动组件层) 功能:1)给用户提供接口 i2c_dev_init  //入口函数 /*申请主设备号*/ register_chrdev(I2C_MAJOR(), &q ...

  7. oneinstack 另一个 lnmp环境一键安装工具

    oneinstack  另一个 http://oneinstack.com/ OneinStack包含以下组合: lnmp(Linux + Nginx+ MySQL+ PHP) lamp(Linux ...

  8. mininet下建立拓扑时关于远程控制器的一个小问题

    最近重装了系统和mininet后,使用mininet时遇到了一点小问题,一开始忽视了细节,使得自己被这个问题困扰了好一会儿,好在后来还是发现了问题所在,故记录下来. $ sudo mn --topo ...

  9. 最全面的 Webview 详解

    前言 现在很多App里都内置了Web网页(Hyprid App),比如说很多电商平台,淘宝.京东.聚划算等等,如下图 那么这种该如何实现呢?其实这是Android里一个叫WebView的组件实现的.今 ...

  10. Make ProgressBar Vertical

    Create a drawable in your Drawable folder called vertical_progress_bar.xml: <?xml version="1 ...