【HDU 2966 k-dimensional Tree 入个门】
·“k-d树是一种分割k维数据空间的数据结构。主要应用于多维空间关键数据的范围搜索和最近邻搜索……”’'
·英文题,述大意:
给出平面内n个点(n<=100000,0<=x,y<=109),我们的任务是按读入顺序输出距离每个点最近的点离它的欧几里得距离的平方。
·分析:
由于是二维,我们可以先考虑一维的情况。若是一维,那我们只需要轻松地维护序列的有序性然后比较一下该元素的左右两个元素最后得到答案,对于维护,我们可以选用Treap,Sort()等。推广到二维,按照上述思路,我们需要维护两个关键字(x,y)的有序性,那么就需要用到嵌套数据结构。这道题的升级版是K维空间内找到最近点,如果我们依旧这样思考,就只能使用树套树套树套树……了吗?
引入KD树的优秀思想——关键字按建树层数轮流起作用。在网络上会经常看见这样的图片来描述KD树的建树方式:
这是啥?这是对二维情况的描述,是使用两个关键字不断划分区间,实质是划分点。这样做是为何?注意我们的目的,是找到最近点!所以我们要找到和这个点的X,Y坐标尽量接近的点,它才可能成为答案。
一颗种在花园里的KD树一般会有这两个过程:
(一)建树:
建树的思想就是上文的关键字轮流划分。我们先回忆线段树的建树,只有一个关键字:下标(或者权值)。所以线段树就可以一直通过mid=l+r>>1不断划分,其实就是默认了唯一关键字。那么对于KD树(本题是二维KD树),建树过程和线段树差不多,也采用二分区间的思想,不过,对于每一层我们关键字交替起作用——例如,本层的关键字轮到了X,那么我们就先找到序列按X排序后的中间数(中位数),然后将小于等于X的点全部塞到左儿子,其余的塞到右儿子,依旧像线段树一样对儿子进行递归操作。我们设M为节点的中位数下标,那么对于建好的KD树的任意节点区间,都满足在当前关键字下,在M左边的点的关键字值小于等于M,在M右边的点的关键字大于M。这样为后来的查询操作打下基础。
(二)查询:
设现在我们要找到离点A(x1,y1)最近的点的距离的平方。最直接的思路就是我们像线段树一样遍历进行查询,对于每个区间[l,r]的M(中位数的下标),为了使得“坐标尽量靠近”,我们规定如果A点的当前关键字大于M点的当前关键字,那么就在左儿子中找,与此同时于每个M都算出与A的距离来更新答案。但是这样的思路有一个缺陷,那就是可能存在这样的情况:一个点的X很大,但是Y很小,但由于X的大使得我们决定访问另一边的点,就错过了它,但是它可能就是答案呐!所以在访问一个儿子结束后,我们需要判断一下,
先如个图啦:
根据上文,我们发现A的关键字权值大于M,所以要在区间[M+1,r]之间查找,假设找到的最优答案是P,但是如果有:Sqr(AM)<P那么说明可能在[l,M]区间中存在贡献答案的点,因为这个式子相当于是用一个关键字的距离平方来与答案比较,只要另一个关键字小,那么完全可能更新答案。
代码之中有一些精妙操作。好吧,它来了。
#include<stdio.h>
#include<algorithm>
#define ll long long
#define S(a) ((1LL*a)*(a))
#define go(i,a,b) for(int i=a;i<=b;i++)
using namespace std;const int N=;
struct P{int p[];}a[N],A[N];int T,D,n;ll ans;
bool cmp(P X,P Y){return X.p[D]<Y.p[D];};
ll Dis(P X,P Y){return S(X.p[]-Y.p[])+S(X.p[]-Y.p[]);}
void build(int l,int r,int d)
{
if(l>r)return;int M=l+r>>;D=d;
nth_element(a+l,a+M,a+r+,cmp);
build(l,M-,d^);build(M+,r,d^);
}
void query(int l,int r,int d,P u)
{
if(l>r)return;
int M=l+r>>,L=l,R=M-;ll dis=Dis(a[M],u);
if(dis&&(ans==||ans>dis))ans=dis;
if(u.p[d]>a[M].p[d])L=M+,R=r;query(L,R,d^,u);
if(S(u.p[d]-a[M].p[d])<ans)query(l+M+-L,r+M--R,d^,u);
}
int main()
{
scanf("%d",&T);while(T--&&scanf("%d",&n))
{
go(i,,n)scanf("%d%d",a[i].p,a[i].p+),A[i]=a[i];build(,n,);
go(i,,n)ans=,query(,n,,A[i]),printf("%lld\n",ans);
}
return ;}//Paul_Guderian
经过濒临疯狂的彻底孤独,
经过狂乱的空空如也的一无所有,
经过一直凉到脚心底的自暴自弃…… ————汪峰《瓦解》
【HDU 2966 k-dimensional Tree 入个门】的更多相关文章
- hdu 5274 Dylans loves tree(LCA + 线段树)
Dylans loves tree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
- Hdu 5274 Dylans loves tree (树链剖分模板)
Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...
- HDU 5423:Rikka with Tree Dijkstra算法
Rikka with Tree Accepts: 207 Submissions: 815 Time Limit: 2000/1000 MS (Java/Others) Memory Limi ...
- Hdu 5416 CRB and Tree (bfs)
题目链接: Hdu 5416 CRB and Tree 题目描述: 给一棵树有n个节点,树上的每条边都有一个权值.f(u,v)代表从u到v路径上所有边权的异或值,问满足f(u,v)==m的(u, v) ...
- webpack实践(一)- 先入个门
一.前言 webpack是个啥呢?看官网的这段描述. webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler) 在我以前做纯html.css. ...
- HDU 6121 Build a tree(完全K叉树)
http://acm.hdu.edu.cn/showproblem.php?pid=6121 题意:给你一颗完全K叉树,求出每棵子树的节点个数的异或和. 思路: 首先需要了解一些关于完全K叉树或满K叉 ...
- 2017多校第7场 HDU 6121 Build a tree K叉树,思维
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6121 题意:一个n个点的完全k叉树,求每个节点的size的异或和. 解法:容易发现,考虑根的所有孩子, ...
- HDU 6121 Build a tree(k叉树的子树大小相异)
http://acm.hdu.edu.cn/showproblem.php?pid=6121 题目大意: 给你一颗 n 个节点的完全 k 叉树,问你这棵树中所有子树结点个数的总异或值. 分析: 我们很 ...
- HDU 5416 CRB and Tree(前缀思想+DFS)
CRB and Tree Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Tot ...
随机推荐
- SDVN
Software Defined Vehicular Networks VANET 车载自组网(VANET)是指在交通环境中车辆之间.车辆与固定接入点之间及车辆与行人之间相互通信组成的开放式移动Ad ...
- http post/get 2种使用方式
public class HttpUtil { //HttpPost public static String executePost(String url, List<NameValue ...
- 日志 --BUG记录
2014-12-15日 在做520wawa的免费推广 部署web应用时 错把path设置为"/*",导致启动tomcat时,导致错误 <Context path=&quo ...
- NOIP2017 列队
https://www.luogu.org/problemnew/show/P3960 p<=500 50分 模拟 每个人的出队只会影响当前行和最后一列 p<=500,有用的行只有500行 ...
- Aache的虚拟主机配置虚拟目录
3. 打开 httpd.conf 文件, 添加如下代码: # Virtual hosts Include conf/extra/httpd-vhosts.conf 如果已存在,将Include前面的# ...
- Java看书学习笔记
1.POM:maven ,项目管理工具存放Jar包的文件2.mybatis-generator-core-1.3.2 生成文件 生成语句: java -jar mybatis-generator-co ...
- MySQL Group Relication 部署环境入门篇
一:环境介绍 cenos 6.7 版本 数据库的版本5.7.19 二:部署规划单机多实例的部署 端口号 数据目录 group_repplicatoon 通信接口 3307 /data ...
- NHibernate优点和缺点:
NHibernate优点: 1.完全的ORM框架. NHibernate对数据库结构提供了较为完整的封装,它将数据库模式映射为较完全的对象模型,支持封装,继续机制,功能较强大,比一般的ORM灵活性高. ...
- mysql中text数据类型
有个小问题记录下: 需要从第三方api接口获取数据,返回的数据的长度不定,设计表的时候设计成了varchar(256):结果存数据的时候提示表字段长度不够. 一直从300改到500,600,700都一 ...
- python3全栈开发-面向对象、面向过程
一. 什么是面向对象的程序设计及为什么要有它 1.面向过程 面向过程的程序设计:核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么......面向过程的设计就好比精心设计好一条流水线,是一种 ...