【kd-tree】专题总结
感谢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】专题总结的更多相关文章
- 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 ...
- k-d tree 学习笔记
以下是一些奇怪的链接有兴趣的可以看看: https://blog.sengxian.com/algorithms/k-dimensional-tree http://zgjkt.blog.uoj.ac ...
- 【BZOJ-2648&2716】SJY摆棋子&天使玩偶 KD Tree
2648: SJY摆棋子 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 2459 Solved: 834[Submit][Status][Discu ...
- K-D Tree
这篇随笔是对Wikipedia上k-d tree词条的摘录, 我认为解释得相当生动详细, 是一篇不可多得的好文. Overview A \(k\)-d tree (short for \(k\)-di ...
- K-D Tree题目泛做(CXJ第二轮)
题目1: BZOJ 2716 题目大意:给出N个二维平面上的点,M个操作,分为插入一个新点和询问到一个点最近点的Manhatan距离是多少. 算法讨论: K-D Tree 裸题,有插入操作. #inc ...
- k-d Tree in TripAdvisor
Today, TripAdvisor held a tech talk in Columbia University. The topic is about k-d Tree implemented ...
- k-d tree算法
k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 应用背景 SIFT算法中做特征点匹配的时候就会利用到k ...
- k-d tree模板练习
1. [BZOJ]1941: [Sdoi2010]Hide and Seek 题目大意:给出n个二维平面上的点,一个点的权值是它到其他点的最长距离减最短距离,距离为曼哈顿距离,求最小权值.(n< ...
- [模板] K-D Tree
K-D Tree K-D Tree可以看作二叉搜索树的高维推广, 它的第 \(k\) 层以所有点的第 \(k\) 维作为关键字对点做出划分. 为了保证划分均匀, 可以以第 \(k\) 维排名在中间的节 ...
- BZOJ3489 A simple rmq problem K-D Tree
传送门 什么可持久化树套树才不会写呢,K-D Tree大法吼啊 对于第\(i\)个数,设其前面最后的与它值相同的位置为\(pre_i\),其后面最前的与它值相同的位置为\(aft_i\),那么对于一个 ...
随机推荐
- BZOJ 1415 聪聪和可可(概率DP)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1415 题意:一个无向图,一个猫.一只老鼠.在任意时刻猫知道老鼠在哪个顶点上.每次移动猫先 ...
- 通过外网IP访问内网
外网服务器:外网IP1,内网IP192.168.2.156 内网服务器:内网IP192.168.2.206 通过访问外网服务器8083端口,转发到内网服务器的8083端口. 在外网服务器设置映射规则: ...
- ubuntu中apt-get安装与默认路径
一.apt-get 安装 deb是debian linus的安装格式,跟red hat的rpm非常相似,最基本的安装命令是:dpkg -i file.deb或者直接双击此文件 dpkg 是Debian ...
- CSS 滤镜(IE浏览器专属其他浏览器不支持)
Filter 属性介绍: 设置或检索对象所应用的滤镜或滤镜集合.此属性仅作用于有布局的对象,如块对象.内联要素要使用该属性,必须先设定对象的 height 或 width 属性,或者设定 positi ...
- HDU 1548 (最基础的BFS了) A strange lift
这是一维的BFS,而且没有什么变形,应该是最基础的BFS了吧 题意: 有这样一个奇葩的电梯,你在第i层的时候你只能选择上或者下Ki层,也就是你只能从第i层到达i+Ki或者i-Ki层.当然电梯最低只能在 ...
- sql DROP 和DELETE、TRUNCATE用法
DROP:删除数据库已存在的表DROP TABLE tbname DELETE:删除记录delete from tbname truncate:清空表,重置索引truncate table tbnam ...
- BZOJ 1123 BLO
tarjan求割点计算答案.注意不是每一棵子树都算答案.开个变量记一下. #include<iostream> #include<cstdio> #include<cst ...
- CocoStudio UI 编辑器的使用
详细教程:http://www.cocoachina.com/bbs/read.php?tid=161567 Table of Contents 1 游戏中的 UI 1.1 基于 Cocos2d-x ...
- Xdebug的安装与使用
php下搭配使用xdebug是十分好的组合,用于php的调试工作,下面分别介绍之: 1 WINDOWS下的安装 下载站点http://www.xdebug.org/ 要确定使用一个跟你的PHP配合 ...
- 解决mysql中文乱码(总)
转自:http://hi.baidu.com/cnvienna/blog/item/2e99efdfd94fc61862279801.html MySQL会出现中文乱码的原因不外乎下列几点: .ser ...