·“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 入个门】的更多相关文章

  1. hdu 5274 Dylans loves tree(LCA + 线段树)

    Dylans loves tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  2. Hdu 5274 Dylans loves tree (树链剖分模板)

    Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...

  3. HDU 5423:Rikka with Tree Dijkstra算法

    Rikka with Tree  Accepts: 207  Submissions: 815  Time Limit: 2000/1000 MS (Java/Others)  Memory Limi ...

  4. Hdu 5416 CRB and Tree (bfs)

    题目链接: Hdu 5416 CRB and Tree 题目描述: 给一棵树有n个节点,树上的每条边都有一个权值.f(u,v)代表从u到v路径上所有边权的异或值,问满足f(u,v)==m的(u, v) ...

  5. webpack实践(一)- 先入个门

    一.前言   webpack是个啥呢?看官网的这段描述. webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)   在我以前做纯html.css. ...

  6. HDU 6121 Build a tree(完全K叉树)

    http://acm.hdu.edu.cn/showproblem.php?pid=6121 题意:给你一颗完全K叉树,求出每棵子树的节点个数的异或和. 思路: 首先需要了解一些关于完全K叉树或满K叉 ...

  7. 2017多校第7场 HDU 6121 Build a tree K叉树,思维

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6121 题意:一个n个点的完全k叉树,求每个节点的size的异或和. 解法:容易发现,考虑根的所有孩子, ...

  8. HDU 6121 Build a tree(k叉树的子树大小相异)

    http://acm.hdu.edu.cn/showproblem.php?pid=6121 题目大意: 给你一颗 n 个节点的完全 k 叉树,问你这棵树中所有子树结点个数的总异或值. 分析: 我们很 ...

  9. HDU 5416 CRB and Tree(前缀思想+DFS)

    CRB and Tree Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Tot ...

随机推荐

  1. 十款不容错过的Swift iOS开源项目及介绍

    1.十款不容错过的Swift iOS开源项目. http://www.csdn.net/article/2014-10-16/2822083-swift-ios-open-source-project ...

  2. Lock(三)查看是谁把表给锁了

    查看是谁把表给锁了 select se1.inst_id as 被阻塞的会话节点, se2.inst_id as 罪魁祸首节点, se1.sid as 被阻塞的会话ID, ob.object_name ...

  3. H5 FormData对象的作用及用法

    JS: function uploadFileAndParam() { var url = "http://localhost:42561/api/upload/UploadPost&quo ...

  4. Angular组件——组件生命周期(二)

    一.view钩子 view钩子有2个,ngAfterViewInit和ngAfterViewChecked钩子. 1.实现ngAfterViewInit和ngAfterViewChecked钩子时注意 ...

  5. 操作MP3文件的元数据

    参见:http://jingyan.baidu.com/article/03b2f78c4d5eae5ea237aee7.html 一.MP3文件的元数据 一个规则的MP3文件大致含有3个部分: TA ...

  6. java基础总结(1)安装jdk

           卸载java java -version yum remove java yum groupjava java        安装java tar -zxvf jdk-8u60-linu ...

  7. python实现归并排序,归并排序的详细分析。

    学习归并排序的过程是十分痛苦的.它并不常用,看起来时间复杂度好像是几种排序中最低的,比快排的时间复杂度还要低,但是它的执行速度不是最快的.很多朋友不理解时间复杂度低为什么运行速度不一定快,这个不清楚的 ...

  8. php 数组对象之间的转换

    在之前我写过php返回json数据简单实例 从5.2版本开始,PHP原生提供json_encode()和json_decode()函数,前者用于编码,后者用于解码. 一.json_encode() 1 ...

  9. 为什么Java不能以返回值区分重载方法?

    读者可能会想:"在区分重载方法的时候,为什么只能以类名和方法的形参列表作为标准呢?能否考虑用方法的返回值来区分呢?" 比如下面两个方法,虽然他们有相同的名字和形式参数,但却很容易区 ...

  10. python 类知识点总结

    python 类知识点总结 面向对象思想: 1.设计的时候,一定要明确应用场景 2.由对象分析定义类的时候,找不到共同特征和技能不用强求 1.简述类.对象.实例化.实例这些名词的含义: 类:从一组对象 ...