【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 ...
随机推荐
- Error contacting service. It is probably not running.
平台:centos-6.3-i386 jdk-7u51 storm 0.9.1 python 2.6.6 hadoop 1.2.1 运行zookeeperd后显示启动成功: JMX enabled ...
- Spring MVC Restful Put方法无法获取参数值
Spring MVC Restful 无法通过@ReqeustParam获取参数值 原因是Tomcat只支持POST/GET获取参数值,对于PUT这些方法需要通过HttpPutFormContentF ...
- 《高级软件测试》11.16.Jira使用说明的撰写和操作视频的录制
今日任务完成情况如下: 小王:完成了测试管理工具jira的使用手册中,基本情况介绍.下载安装部分的撰写工作:小高:参考官方手册,结合自己的实际使用体会,对jira的基本组成及其工作流程进行了介绍:小陈 ...
- 技术文档分享_linux中生成考核用的GPT分区表结构修复
注:历史版本,后期改用python实现了 实验一: 目的:用于生成大量模拟破坏GPT分区结构案例,并生成唯一方式修复后的评判方法.故障:在一个完整的GPT分区磁盘上,丢失了GPT主分区表,或备份分区表 ...
- 直方图均衡化及matlab实现
在处理图像时,偶尔会碰到图像的灰度级别集中在某个小范围内的问题,这时候图像很难看清楚.比如下图: 它的灰度级别,我们利用一个直方图可以看出来(横坐标从0到255,表示灰度级别,纵坐标表示每个灰度级别的 ...
- day-1 用python编写一个简易的FTP服务器
从某宝上购买了一份<Python神经网络深度学习>课程,按照视频教程,用python语言,写了一个简易的FTP服务端和客户端程序,以前也用C++写过聊天程序,编程思路差不多,但是pytho ...
- php的开发的apache的配置及伪静态的应用
1.Apache之所以能够解析php代码是游览器首先发送数据到模版页面,然后模版页提交数据到php页面,然后php代码经过Apache解析过后生成结果的,所以是 在Apache的配置文件中是可以看到开 ...
- axure 预览"HTTP/1.1 302 Found"
使用Axure编辑原型时,点击预览出现"HTTP/1.1 302 Found" 第一想到的就是重新安装Axure和检查原型文件是否损坏,验证后证明前Axure和.rp文件都是完好的 ...
- maven入门(1-3)构建简单的maven项目
1. 用Maven 命令创建一个简单的Maven项目 在cmd中运行如下命令: mvn archetype:generate -DgroupId=com.mycompany.app -Dartifac ...
- KNN算法简单应用
这里是写给小白看的,大牛路过勿喷. 1 KNN算法简介 KNN(K-Nearest Neighbor)工作原理:存在一个样本数据集合,也称为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集 ...