·“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. Scrum 冲刺 第三日

    Scrum 冲刺 第三日 目录 要求 项目链接 燃尽图 问题 今日任务 明日计划 成员贡献量 要求 各个成员今日完成的任务(如果完成的任务为开发或测试任务,需给出对应的Github代码签入记录截图:如 ...

  2. 201421123042 《Java程序设计》第11周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 2. 书面作业 本次PTA作业题集多线程 1. 源代码阅读:多线程程序BounceThread 1.1 BallR ...

  3. php的set_time_limit()函数

    set_time_limit(0); 括号里边的数字是执行时间,如果为零说明永久执行直到程序结束,如果为大于零的数字,则不管程序是否执行完成,到了设定的秒数,程序结束. 一个简单的例子,在网页里显示1 ...

  4. io文本加密

    文本加密习题 package io; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.Inpu ...

  5. python全栈开发-re模块(正则表达式)应用(字符串的处理)

    一.概述 就其本质而言,正则表达式(或 RE)是一种小型的.高度专业化的编程语言,要讲他的具体用法要讲一本书!它内嵌在Python中,并通过 re 模块实现.你可以为想要匹配的相应字符串集指定规则:该 ...

  6. Angular 学习笔记 ( CDK - Overlays )

    更新 : 2018-01-30 ng 的 overlap 在关闭的时候对 backdrop 做了一个 style pointer 目的是让 backdrop 不被 2 次点击, 但是呢,  css p ...

  7. SpringCloud的注解:EnableEurekaClient vs EnableDiscoveryClient

    What's the difference between EnableEurekaClient and EnableDiscoveryClient? In some applications, I ...

  8. zabbix配置微信报警

    首先我们先目睹下微信报警的效果 接下来我们正式开始操作. 一:注册企业微信. 打开企业微信注册:http://work.weixin.qq.com 根据以上提示填入相应的内容,然后注册即可. 二:登录 ...

  9. shiro中CacheManager相关的类结构介绍,提供redis Cache实现

    cacheManager主要用于对shiro中的session.realm中的认证信息.授权信息进行缓存. 1.类结构 2.接口及类介绍 CacheManager 提供根据名字获取cache的作用. ...

  10. UVA732【DFS+栈】

    题目:已知两个单词,利用一个栈,将第一个单词变成第二个单词,求出所有可能的操作序列. #include <stdio.h> #include<iostream> #includ ...