【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\),那么对于一个 ...
随机推荐
- Hosting Your Own NuGet Feeds
Hosting Your Own NuGet Feeds Hosting the NuGet Gallery Locally in IIS https://github.com/NuGet/NuGet ...
- [LintCode]perfect-squares(DP)
题目链接:http://www.lintcode.com/zh-cn/problem/perfect-squares/ 就是求最小价值的完全背包,初始化dp[i]=i,假设全是1的时候是最多的,之后就 ...
- cocos2dx 坐标系 -转
(原文出处找不到了) 无论是搞2d还是3d开发,最需要搞清楚的就是坐标系,这部分混乱的话就没啥奔头了.所以玩cocos2d,一上来就先把各种与坐标有关的东西搞清楚. 基本的两个坐标系:屏幕坐标系和GL ...
- 【温故知新】C#委托delegate
在c#的学习过程中,学到委托与事件总会迷糊一段时间,迷糊过后自然而就似懂非懂了~,所以最近我打算把以前所学的迷糊过的知识总结,温故知新,总结记录下来. 首先,我们来看一下msdn对委托的定义: del ...
- Open Explorer Plugin for Eclipse (eclipse 插件 在eclipse里面打开文件目录)
就是在eclipse里面直接打开文件所在的目录地址 只要将下面的jar 文件放到你的 “$ECLIPSE_HOME/plugins” 下面,重启eclipse就ok了 要想卸载的话 停止eclip ...
- 【转】PWM占空比和分辨率
占空比是接通时间与周期之比冲量相等而形状不同的窄脉冲加在具有惯性的环节上时,其效果基本相同占空比:就是输出的PWM中,高电平保持的时间与该PWM的时钟周期的时间之比,如一个PWM的频率是1000Hz, ...
- 如何使用LiveSuite debian img格式的镜像文件刷入nand
1. liveSuite启动后 2. 选择固件(就是对应的img文件) 3. 将cubieboard板子的fel按钮按住不要松,然后使用otg接口线插入电脑和cubieboard板子,直到liveSu ...
- 浅谈配置chrome浏览器允许跨域操作的方法
浅谈配置chrome浏览器允许跨域操作的方法 一:(Lying人生感悟.可忽略) 最近有一天,对着镜子,发现满脸疲惫.脸色蜡黄.头发蓬松.眼神空洞,于是痛诉着说生活的不如意,工作没激情,工资不高,一个 ...
- quartz的触发器CronTriggerBean 配置
一个Quartz的CronTrigger表达式分为七项子表达式,其中每一项以空格隔开,从左到右分别是:秒,分,时,月的某天,月,星期的某天,年:其中年不是必须的,也就是说任何一个表达式最少需要六项! ...
- HDU 2059 龟兔赛跑
受上一道题影响,我本来想着开一个二维数组来表示充电和不充电的状态. 可这样就有一个问题,如果没有充电,那么在下一个阶段就有剩余的电量. 这样问题貌似就不可解了,难道是因为不满足动态规划的无后效性这一条 ...