感谢orz神·小黑的指导

kd-tree就是用来计算若干维空间k近/远点的数(shou)据(suo)结(you)构(hua)

建树

假设题目是k维的点

第deep层就是用deep%k+1维把所有点分为两块

取deep%k+1维中位数的点做为当前子树的根节点

再把该维比这个点小的点扔到左子树 比这个点大的扔到右子树 递归处理

详见代码

 void Sort(ll l,ll r,ll k){ cmpp=k; sort(kd+l,kd+r+,cmp); }
ll build(ll l,ll r,ll deep){
if (l==r){
kd[l].lc=kd[r].rc=;
return l;
}
Sort(l,r,deep);
ll mid=(l+r)/;
if (l<mid) kd[mid].lc=build(l,mid-,deep%k+);
else kd[mid].lc=;
if (mid<r) kd[mid].rc=build(mid+,r,deep%k+);
else kd[mid].rc=;
return mid;
}

查询

询问离点S的前m近点 说它是搜索优化就是因为这里- -

维护大根堆记录答案 当元素个数小于m时直接push

反正判断有木有 比最大值小 有就pop再push

当搜索当t点是先用该点到S的距离维护堆

再判断如果S的deep%k+1维 比t点该维小就先搜索左子树 否则搜索右子树

搜索完一颗子树后 判断如果S到t点deep%k+1维的距离就≥ans显然继续搜索没用 就不继续搜索 否则搜索另一颗子树

代码

 void push(ll t){
ll dis=getdis(S,poi[t]);
if (size==m){
if (dis>que.top().dis) return;
else{
que.pop();
que.push(info(dis,t));
}
}else{
++size;
que.push(info(dis,t));
}
}
void makeans(ll t,ll deep){
if (!t) return;
push(kd[t].t);
if (S.d[deep]<=kd[t].p.d[deep]){
makeans(kd[t].lc,deep%k+);
if (size<m || que.top().dis>sqr(S.d[deep]-kd[t].p.d[deep])) makeans(kd[t].rc,deep%k+);
}else{
makeans(kd[t].rc,deep%k+);
if (size<m || que.top().dis>sqr(S.d[deep]-kd[t].p.d[deep])) makeans(kd[t].lc,deep%k+);
}
}

最远点

这里讲的都是m近点- -

如果是m远点其实是差不多的 只是维护的东西不太一样

需要维护每维的min和max

询问的时候基本同理yy下即可

求k位距离S的m近点代码

 #include <cstdio>
#include <algorithm>
#include <queue>
typedef long long ll;
using namespace std;
const ll N=;
struct inpo{
ll d[];
}poi[N],S,ans[];
struct inkd{
ll t,lc,rc;
inpo p;
inkd(const ll a=,const ll b=,const ll c=):
t(a),lc(b),rc(c){}
}kd[N];
struct info{
ll dis,t;
info(const ll a=,const ll b=):
dis(a),t(b){}
};
priority_queue <info> que;
ll root,n,k,m,t,cmpp,size;
inline bool operator <(info a,info b){ return a.dis<b.dis; }
inline bool cmp(inkd a,inkd b){ return a.p.d[cmpp]<b.p.d[cmpp]; }
void Sort(ll l,ll r,ll k){ cmpp=k; sort(kd+l,kd+r+,cmp); }
ll sqr(ll x){ return x*x; }
ll getdis(inpo a,inpo b){
ll res=;
for (ll i=;i<=k;i++) res+=sqr(a.d[i]-b.d[i]);
return res;
}
ll build(ll l,ll r,ll deep){
if (l==r){
kd[l].lc=kd[r].rc=;
return l;
}
Sort(l,r,deep);
ll mid=(l+r)/;
if (l<mid) kd[mid].lc=build(l,mid-,deep%k+);
else kd[mid].lc=;
if (mid<r) kd[mid].rc=build(mid+,r,deep%k+);
else kd[mid].rc=;
return mid;
}
void push(ll t){
ll dis=getdis(S,poi[t]);
if (size==m){
if (dis>que.top().dis) return;
else{
que.pop();
que.push(info(dis,t));
}
}else{
++size;
que.push(info(dis,t));
}
}
void makeans(ll t,ll deep){
if (!t) return;
push(kd[t].t);
if (S.d[deep]<=kd[t].p.d[deep]){
makeans(kd[t].lc,deep%k+);
if (size<m || que.top().dis>sqr(S.d[deep]-kd[t].p.d[deep])) makeans(kd[t].rc,deep%k+);
}else{
makeans(kd[t].rc,deep%k+);
if (size<m || que.top().dis>sqr(S.d[deep]-kd[t].p.d[deep])) makeans(kd[t].lc,deep%k+);
}
}
int main(){
freopen("hdu4347.in","r",stdin);
freopen("hdu4347.out","w",stdout);
while (~scanf("%I64d%I64d",&n,&k)){
for (ll i=;i<=n;i++){
for (ll j=;j<=k;j++) scanf("%I64d",&poi[i].d[j]);
kd[i].t=i,kd[i].p=poi[i];
}
root=build(,n,);
scanf("%I64d",&t);
for (;t;t--){
size=;
for (ll i=;i<=k;i++) scanf("%I64d",&S.d[i]);
scanf("%I64d",&m);
printf("the closest %I64d points are:\n",m);
makeans(root,);
for (ll i=;i<=m;i++){
ans[i]=poi[que.top().t];
que.pop();
}
for (ll i=m;i;i--){
for (ll j=;j<=k;j++){
printf("%I64d",ans[i].d[j]);
if (j<k) printf(" ");
}
puts("");
}
}
}
fclose(stdin);
fclose(stdout);
}

【kd-tree】专题总结的更多相关文章

  1. AOJ DSL_2_C Range Search (kD Tree)

    Range Search (kD Tree) The range search problem consists of a set of attributed records S to determi ...

  2. k-d tree 学习笔记

    以下是一些奇怪的链接有兴趣的可以看看: https://blog.sengxian.com/algorithms/k-dimensional-tree http://zgjkt.blog.uoj.ac ...

  3. 【BZOJ-2648&2716】SJY摆棋子&天使玩偶 KD Tree

    2648: SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2459  Solved: 834[Submit][Status][Discu ...

  4. K-D Tree

    这篇随笔是对Wikipedia上k-d tree词条的摘录, 我认为解释得相当生动详细, 是一篇不可多得的好文. Overview A \(k\)-d tree (short for \(k\)-di ...

  5. K-D Tree题目泛做(CXJ第二轮)

    题目1: BZOJ 2716 题目大意:给出N个二维平面上的点,M个操作,分为插入一个新点和询问到一个点最近点的Manhatan距离是多少. 算法讨论: K-D Tree 裸题,有插入操作. #inc ...

  6. k-d Tree in TripAdvisor

    Today, TripAdvisor held a tech talk in Columbia University. The topic is about k-d Tree implemented ...

  7. k-d tree算法

    k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 应用背景 SIFT算法中做特征点匹配的时候就会利用到k ...

  8. k-d tree模板练习

    1. [BZOJ]1941: [Sdoi2010]Hide and Seek 题目大意:给出n个二维平面上的点,一个点的权值是它到其他点的最长距离减最短距离,距离为曼哈顿距离,求最小权值.(n< ...

  9. [模板] K-D Tree

    K-D Tree K-D Tree可以看作二叉搜索树的高维推广, 它的第 \(k\) 层以所有点的第 \(k\) 维作为关键字对点做出划分. 为了保证划分均匀, 可以以第 \(k\) 维排名在中间的节 ...

  10. BZOJ3489 A simple rmq problem K-D Tree

    传送门 什么可持久化树套树才不会写呢,K-D Tree大法吼啊 对于第\(i\)个数,设其前面最后的与它值相同的位置为\(pre_i\),其后面最前的与它值相同的位置为\(aft_i\),那么对于一个 ...

随机推荐

  1. SASS -- 基本认识

    SASS 是一种 CSS 的开发工具,提供了许多便利的写法,大大节省了设计者的时间,使得 CSS 的开发,变得简单和可维护. SASS 提供四个编译风格的选项: * nested:嵌套缩进的 css ...

  2. Hadoop集群(第8期)_HDFS初探之旅

    1.HDFS简介 HDFS(Hadoop Distributed File System)是Hadoop项目的核心子项目,是分布式计算中数据存储管理的基础,是基于流数据模式访问和处理超大文件的需求而开 ...

  3. windows主机无法访问服务器

    在CentOS下安装配置hadoop的时候,总显示因为网络端口而导致主机无法访问服务器,遂打算先关闭一下防火墙. 偶然看到防火墙的配置操作说明,感觉不错.执行”setup”命令启动文字模式配置实用程序 ...

  4. Java里面instanceof怎么实现的

    开始完全一头雾水呀,后面看了Java指令集的介绍,逐渐理解了. https://www.zhihu.com/question/21574535/answer/18998914 下面这个答案比较直白 你 ...

  5. R语言 rwordseg包的下载

    在CRAN中没有,如果通过R下载经常会出错,使用以下地址下载后加载本地包 http://R-Forge.R-project.org/bin/windows/contrib/3.0/Rwordseg_0 ...

  6. bzoj4199

    看到这题我就伤心,当初想到了正解却因为各种sb原因没有写…… 好吧,其实我的正解是比较挫的…… 大家似乎都用了后缀数组,我用了后缀自动机(后缀树) 其实SAM是很好想得,用SAM建出后缀树后 我们考虑 ...

  7. 基于Bootstrap的超酷jQuery开关按钮插件

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJgAAAA2CAIAAAC0tsfoAAAB/0lEQVR4nO3bQWrCQBTGcc/mbVz0DD

  8. C语言之宏

    所谓的宏就是一种预处理命令,什么是与处理呢?即在编译过程之前先对程序代码做出的必要的转换处理.宏有两个作用: 1.当遇到需要将程序某个特定的数量在程序中出现的所有实例通通加以修改时,程序只需改动一处即 ...

  9. HDU 5317 RGCDQ (质数筛法,序列)

    题意:从1~1000,000的每个自然数质因子分解,不同因子的个数作为其f 值,比如12=2*2*3,则f(12)=2.将100万个数转成他们的f值后变成新的序列seq.接下来T个例子,每个例子一个询 ...

  10. HDU 1496 Train Problem I 火车问题1(桟,水)

    题意: 给出两个串,串中的数字i 代表编号为i的火车进入车站的顺序,车站如桟一样,先进后出.第二个串是火车出站的顺序,问若按照第一个串那样进站,是否有可能如第二个串一样的出站顺序?火车顶多9辆,即1- ...