kd tree学习笔记 (最近邻域查询)

https://zhuanlan.zhihu.com/p/22557068

http://blog.csdn.net/zhjchengfeng5/article/details/7855241

 

KD树在算法竞赛中主要用来做各种各样的平面区域查询,包含则累加直接返回,相交则继续递归,相离的没有任何贡献也直接返回。可以处理圆,三角形,矩形等判断起来相对容易的平面区域内的符合加法性质的操作。

比如查询平面内欧几里得距离最近的点的距离。

kdtree其实有点像搜索,暴力+剪枝。

每次从根结点向下搜索,并进行剪枝操作,判断是否有必要继续搜索。

它是通过横一刀,竖一刀,横一刀再竖一刀将平面进行分割,建立二叉树。

建树的复杂度是O(nlogn), 每次用nth_element()在线性时间内取出中位数。 T(n) = 2T(n/2) + O(n) = O(nlogn)

查询复杂度呢? 据第二个链接的博客说最坏是O( sqrt(n) ) 的。并不会分析查询复杂度。

 

HDU2966 裸kdtree

题意:给平面图上N(≤ 100000)个点,对每个点,找到其他 欧几里德距离 离他最近的点,输出他们之间的距离。保证没有重点。

 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 #define N 200010
 5 const ll inf = 1e18;
 6 int n,i,id[N],root,cmp_d;
 7 int x, y;
 8 struct node{int d[2],l,r,Max[2],Min[2],val,sum,f;}t[N];
 9 bool cmp(const node&a,const node&b){return a.d[cmp_d]<b.d[cmp_d];}
10 void umax(int&a,int b){if(a<b)a=b;}
11 void umin(int&a,int b){if(a>b)a=b;}
12 void up(int x){
13     if(t[x].l){
14         umax(t[x].Max[0],t[t[x].l].Max[0]);
15         umin(t[x].Min[0],t[t[x].l].Min[0]);
16         umax(t[x].Max[1],t[t[x].l].Max[1]);
17         umin(t[x].Min[1],t[t[x].l].Min[1]);
18     }
19     if(t[x].r){
20         umax(t[x].Max[0],t[t[x].r].Max[0]);
21         umin(t[x].Min[0],t[t[x].r].Min[0]);
22         umax(t[x].Max[1],t[t[x].r].Max[1]);
23         umin(t[x].Min[1],t[t[x].r].Min[1]);
24     }
25 }
26 int build(int l,int r,int D,int f){
27     int mid=(l+r)>>1;
28     cmp_d=D,std::nth_element(t+l,t+mid,t+r+1,cmp);
29     id[t[mid].f]=mid;
30     t[mid].f=f;
31     t[mid].Max[0]=t[mid].Min[0]=t[mid].d[0];
32     t[mid].Max[1]=t[mid].Min[1]=t[mid].d[1];
33     //t[mid].val=t[mid].sum=0;
34     if(l!=mid)t[mid].l=build(l,mid-1,!D,mid);else t[mid].l=0;
35     if(r!=mid)t[mid].r=build(mid+1,r,!D,mid);else t[mid].r=0;
36     return up(mid),mid;
37 }
38 
39 ll dis(ll x1, ll y1, ll x, ll y) {
40     ll xx = x1-x, yy = y1-y;
41     return xx*xx+yy*yy;
42 }
43 ll dis(int p, ll x, ll y){//估价函数, 以p为子树的最小距离
44     ll xx = 0, yy = 0;
45     if(t[p].Max[0] < x) xx = x-t[p].Max[0];
46     if(t[p].Min[0] > x) xx = t[p].Min[0]-x;
47     if(t[p].Max[1] < y) yy = y-t[p].Max[1];
48     if(t[p].Min[1] > y) yy = t[p].Min[1]-y;
49     return xx*xx+yy*yy;
50 }
51 ll ans;
52 void query(int p){
53     ll dl = inf, dr = inf, d = dis(t[p].d[0], t[p].d[1], x, y);
54     if(d) ans = min(ans, d);
55 
56     if(t[p].l) dl = dis(t[p].l, x, y);
57     if(t[p].r) dr = dis(t[p].r, x, y);
58     if(dl < dr){
59         if(dl < ans) query(t[p].l);
60         if(dr < ans) query(t[p].r);
61     }
62     else {
63         if(dr < ans) query(t[p].r);
64         if(dl < ans) query(t[p].l);
65     }
66 }
67 
68 int main(){
69     int T; scanf("%d", &T);
70     while(T--){
71         scanf("%d", &n);
72         for(int i = 1; i <= n; i++){
73             scanf("%d%d", &t[i].d[0], &t[i].d[1]);
74             t[i].f = i;
75         }
76         int rt = build(1, n, 0, 0);
77         for(int i = 1; i <= n; i++){
78             ans = inf;
79             x = t[ id[i] ].d[0], y = t[ id[i] ].d[1];
80             query(rt);
81             printf("%lld\n", ans);
82         }
83     }
84     return 0;
85 }
View Code

 

BZOJ2648

题意:给出n个点,接下来m个操作,每次插入一个点,或者询问离询问点的最近曼哈顿距离。

  1 #include <bits/stdc++.h>
  2 #define ll long long
  3 using namespace std;
  4 #define N 1000010
  5 const ll inf = 1e18;
  6 int n,m,i,id[N],root,cmp_d,rt;
  7 int x, y;
  8 struct node{int d[2],l,r,Max[2],Min[2],val,sum,f;}t[N];
  9 bool cmp(const node&a,const node&b){return a.d[cmp_d]<b.d[cmp_d];}
 10 void umax(int&a,int b){if(a<b)a=b;}
 11 void umin(int&a,int b){if(a>b)a=b;}
 12 void up(int x){
 13     if(t[x].l){
 14         umax(t[x].Max[0],t[t[x].l].Max[0]);
 15         umin(t[x].Min[0],t[t[x].l].Min[0]);
 16         umax(t[x].Max[1],t[t[x].l].Max[1]);
 17         umin(t[x].Min[1],t[t[x].l].Min[1]);
 18     }
 19     if(t[x].r){
 20         umax(t[x].Max[0],t[t[x].r].Max[0]);
 21         umin(t[x].Min[0],t[t[x].r].Min[0]);
 22         umax(t[x].Max[1],t[t[x].r].Max[1]);
 23         umin(t[x].Min[1],t[t[x].r].Min[1]);
 24     }
 25 }
 26 int build(int l,int r,int D,int f){
 27     int mid=(l+r)>>1;
 28     cmp_d=D,std::nth_element(t+l,t+mid,t+r+1,cmp);
 29     id[t[mid].f]=mid;
 30     t[mid].f=f;
 31     t[mid].Max[0]=t[mid].Min[0]=t[mid].d[0];
 32     t[mid].Max[1]=t[mid].Min[1]=t[mid].d[1];
 33     //t[mid].val=t[mid].sum=0;
 34     if(l!=mid)t[mid].l=build(l,mid-1,!D,mid);else t[mid].l=0;
 35     if(r!=mid)t[mid].r=build(mid+1,r,!D,mid);else t[mid].r=0;
 36     return up(mid),mid;
 37 }
 38 
 39 ll dis(ll x1, ll y1, ll x, ll y) {
 40     return abs(x1-x)+abs(y1-y);
 41     //ll xx = x1-x, yy = y1-y;
 42     //return xx*xx+yy*yy;
 43 }
 44 ll dis(int p, ll x, ll y){//估价函数, 以p为子树的最小距离
 45     ll xx = 0, yy = 0;
 46     if(t[p].Max[0] < x) xx = x-t[p].Max[0];
 47     if(t[p].Min[0] > x) xx = t[p].Min[0]-x;
 48     if(t[p].Max[1] < y) yy = y-t[p].Max[1];
 49     if(t[p].Min[1] > y) yy = t[p].Min[1]-y;
 50     return xx+yy;
 51     //return xx*xx+yy*yy;
 52 }
 53 ll ans;
 54 void ins(int now, int k, int x){
 55     if(t[x].d[k] >= t[now].d[k]){
 56         if(t[now].r) ins(t[now].r, !k, x);
 57         else
 58             t[now].r = x, t[x].f = now;
 59     }
 60     else {
 61         if(t[now].l) ins(t[now].l, !k, x);
 62         else t[now].l = x, t[x].f = now;
 63     }
 64     up(now);
 65 }
 66 void query(int p){
 67     ll dl = inf, dr = inf, d = dis(t[p].d[0], t[p].d[1], x, y);
 68     ans = min(ans, d);
 69 
 70     if(t[p].l) dl = dis(t[p].l, x, y);
 71     if(t[p].r) dr = dis(t[p].r, x, y);
 72     if(dl < dr){
 73         if(dl < ans) query(t[p].l);
 74         if(dr < ans) query(t[p].r);
 75     }
 76     else {
 77         if(dr < ans) query(t[p].r);
 78         if(dl < ans) query(t[p].l);
 79     }
 80 }
 81 
 82 int main(){
 83     scanf("%d%d", &n, &m);
 84     for(int i = 1; i <= n; i++)
 85         scanf("%d%d", &t[i].d[0], &t[i].d[1]);
 86     rt = build(1, n, 0, 0);
 87     while(m--){
 88         int op;
 89         scanf("%d%d%d", &op, &x, &y);
 90         if(op == 1){
 91             n++;
 92             t[n].l = t[n].r = 0;
 93             t[n].Max[0] = t[n].Min[0] = t[n].d[0] = x;
 94             t[n].Max[1] = t[n].Min[1] = t[n].d[1] = y;
 95             ins(rt, 0, n);
 96         }
 97         else{
 98             ans = inf;
 99             query(rt);
100             printf("%lld\n", ans);
101         }
102     }
103     return 0;
104 }
View Code

 

BZOJ3053

题意:k维坐标系下的最近的m个点。直接对于每一个询问都在kdtree中询问m次最近点,每次找到一个最近点对需要把它记录下来,用堆维护即可。

  1 #include <bits/stdc++.h>
  2 #define ll long long
  3 #define mp make_pair
  4 
  5 using namespace std;
  6 #define N 50010
  7 const ll inf = 1e18;
  8 int n,m,k,i,id[N],root,cmp_d,rt;
  9 int x, y, num;
 10 struct node{int d[5],l,r,Max[5],Min[5],val,sum,f;}t[N];
 11 bool cmp(const node&a,const node&b){return a.d[cmp_d]<b.d[cmp_d];}
 12 void umax(int&a,int b){if(a<b)a=b;}
 13 void umin(int&a,int b){if(a>b)a=b;}
 14 void up(int x){
 15     for(int i = 0; i < k; i++){
 16         if(t[x].l){
 17             umax(t[x].Max[i],t[t[x].l].Max[i]);
 18             umin(t[x].Min[i],t[t[x].l].Min[i]);
 19         }
 20         if(t[x].r){
 21             umax(t[x].Max[i],t[t[x].r].Max[i]);
 22             umin(t[x].Min[i],t[t[x].r].Min[i]);
 23         }
 24     }
 25 }
 26 int build(int l,int r,int D,int f){
 27     int mid=(l+r)>>1;
 28     cmp_d=D,std::nth_element(t+l,t+mid,t+r+1,cmp);
 29     id[t[mid].f]=mid;
 30     t[mid].f=f;
 31     for(int i = 0; i < k; i++)
 32     t[mid].Max[i]=t[mid].Min[i]=t[mid].d[i];
 33     //t[mid].Max[1]=t[mid].Min[1]=t[mid].d[1];
 34     //t[mid].val=t[mid].sum=0;
 35     if(l!=mid)t[mid].l=build(l,mid-1,(D+1)%k,mid);else t[mid].l=0;
 36     if(r!=mid)t[mid].r=build(mid+1,r,(D+1)%k,mid);else t[mid].r=0;
 37     return up(mid),mid;
 38 }
 39 int qx[5];
 40 ll dis(int p){//估价函数, 以p为子树的最小距离
 41     ll ret = 0, ans = 0;
 42     for(int i = 0; i < k; i++) {
 43         ret = 0;
 44         if(t[p].Max[i] < qx[i]) ret = qx[i]-t[p].Max[i];
 45         if(t[p].Min[i] > qx[i]) ret = t[p].Min[i]-qx[i];
 46         ans += ret*ret;
 47     }
 48     return ans;
 49 }
 50 ll getdis(int p){
 51     ll ans = 0;
 52     for(int i = 0; i < k; i++)
 53         ans += (qx[i]-t[p].d[i])*(qx[i]-t[p].d[i]);
 54     return ans;
 55 }
 56 void ins(int now, int k, int x){
 57     if(t[x].d[k] >= t[now].d[k]){
 58         if(t[now].r) ins(t[now].r, !k, x);
 59         else
 60             t[now].r = x, t[x].f = now;
 61     }
 62     else {
 63         if(t[now].l) ins(t[now].l, !k, x);
 64         else t[now].l = x, t[x].f = now;
 65     }
 66     up(now);
 67 }
 68 ll ret;
 69 multiset< pair<int, int> > ans;
 70 void query(int p){
 71     ll dl = inf, dr = inf, d = getdis(p);
 72     ans.insert( mp((int)d, p) );
 73     if(ans.size() > num){
 74         multiset< pair<int, int> >::iterator it = ans.end();
 75         it--;
 76         ans.erase(it);
 77     }
 78     ret = (*ans.rbegin()).first;
 79     if(t[p].l) dl = dis(t[p].l);
 80     if(t[p].r) dr = dis(t[p].r);
 81     if(dl < dr){
 82         if(dl < ret||ans.size() < num) query(t[p].l);
 83         if(dr < ret||ans.size() < num) query(t[p].r);
 84     }
 85     else {
 86         if(dr < ret||ans.size() < num) query(t[p].r);
 87         if(dl < ret||ans.size() < num) query(t[p].l);
 88     }
 89 }
 90 
 91 int main(){
 92     while(~scanf("%d%d", &n, &k)){
 93         for(int i = 1; i <= n; i++){
 94             for(int j = 0; j < k; j++)
 95                 scanf("%d", &t[i].d[j]);
 96         }
 97         rt = build(1, n, 0, 0);
 98         scanf("%d", &m);
 99         while(m--){
100             for(int i = 0; i < k; i++)
101                 scanf("%d", qx+i);
102             scanf("%d", &num);
103             ans.clear();
104             query(rt);
105             printf ("the closest %d points are:\n", num);
106             for(multiset< pair<int, int> >::iterator it = ans.begin(); it != ans.end(); it++){
107                 int pos = (*it).second;
108                 for(int i = 0; i < k; i++)
109                     printf("%d%c", t[pos].d[i], " \n"[i == k-1]);
110             }
111         }
112     }
113     return 0;
114 }
View Code

 

转载于:https://www.cnblogs.com/dirge/p/6091241.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/456894.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图像影音型计算机主板选择什么,电脑主板型号在哪里看? 每日一答

电脑主板型号在哪里看&#xff1f;想要看主板的型号其实非常简单&#xff0c;一般来说&#xff0c;主板上都会有一个专门的身份标识&#xff0c;位于PCI-E显卡插槽之间&#xff0c;比如下方这张图&#xff0c;就清晰地写明了MAXIMUS X APEX的标识&#xff0c;熟悉的玩家一眼就能…

使用叶神模拟器无法访问本机服务器的问题(报错:java.net.ConnectException: failed to connect to /127.0.0.1 (port 5000) )

最近打算用夜神模拟器来和本机服务器做一些信息交互的功能&#xff0c;但是服务器搭建好了&#xff0c;用叶神模拟器却无法访问。折腾了大半天才发现原来是模拟器的问题。 具体过程如下&#xff1a; 搭建好服务器后&#xff0c;在本机上访问“http://127.0.0.1:5000/”&#…

初学大数据之如何选择机器学习算法

最近在国外网站看到一篇不错的文章&#xff0c;所以就翻译过来给大家分享一下。主要介绍初学者怎么选择机器学习算法,希望对各位初学者有帮助。 原文如下: 一个初学者面临各种机器学习算法的典型问题是“我应该使用哪种算法&#xff1f;”问题的答案取决于许多因素&#xff0…

Django查询 – id vs pk

当编写django查询时&#xff0c;可以使用id / pk作为查询参数。 Object.objects.get(id1) Object.objects.get(pk1) pk代表主键(primary key)&#xff0c; pk更加独立于实际的主键字段&#xff0c;即不必关心主键字段是否被称为id或object_id或其他。 如果您具有不同主键字…

Tomcat的Session管理(三)

摘要&#xff1a;PersistentManager与StandardManager的异同。 之前两篇关于session的文章主要讨论了session相关的创建、查询、过期处理。而我们查看源码的时候都是默认实现是StandardManager类&#xff0c;实际上实现也可以是PersistentManager类&#xff0c;下面我们就查看下…

稳定和性能如何兼顾?58大数据平台的技术演进与实践

作者&#xff5c;赵健博 编辑&#xff5c;尚剑 本文将为你分享58大数据平台在最近一年半内技术演进的过程&#xff0c;包括&#xff1a;58大数据平台目前的整体架构是怎么样的&#xff1b;最近一年半的时间内我们面临的问题、挑战以及技术演进过程&#xff1b;以及未来的规划。…

Random Forest算法简介

转自JoinQuant量化课堂 一、相关概念 分类器&#xff1a;分类器就是给定一个样本的数据&#xff0c;判定这个样本属于哪个类别的算法。例如在股票涨跌预测中&#xff0c;我们认为前一天的交易量和收盘价对于第二天的涨跌是有影响的&#xff0c;那么分类器就是通过样本的交易量…

简单交互

控件有着各种事件&#xff0c;例如被点击的时候&#xff0c;我们可以在事件里面添加动作和命令&#xff0c;让控件可以和用户交互&#xff0c;这里我们演示一个简单的交互&#xff1a;当用户点击文字控件的时候&#xff0c;它开始动画向下移动然后动画旋转&#xff0c;效果入下…

综合素质计算机考点,教师资格证小学综合素质考点及考试真题:信息处理能力...

小学综合素质考点及考试真题——信息处理能力大纲要求&#xff1a;具有运用工具书检索信息、资料的能力。具有运用网络检索、交流信息的能力。具有对信息进行筛选、分类、存储和应用的能力。具有运用教育测量知识进行数据分析与处理的能力。具有根据教育教学的需要&#xff0c;…

API文档自动生成

本文主要讲述自动化API文档生成——apidoc。网上有几个篇文章都只是介绍apidoc的&#xff0c;具体怎么在自己的项目中使用以及与其他配合使用都是没介绍的。最近开始玩服务器&#xff0c;了解到了有Windows与Linux之间共享文件的方法&#xff0c;就是samba。然后具体和apidoc结…

机器学习笔记之SVM(SVR)算法

学过SVM后&#xff0c;看了那么多别人的文章&#xff0c;是时候自己总结一波了。权当写的笔记供自己日后再回顾吧。 PS:结合自己在工作过程中&#xff08;我这里用SVR做股票预测&#xff09;用到的知识来写的&#xff0c;不会很全面&#xff0c;若有些知识这里没提及读者可自行…

[转]基于图的机器学习技术:谷歌众多产品和服务背后的智能

近来机器学习领域实现了很多重大的进展&#xff0c;这些进展让计算机系统具备了解决复杂的真实世界问题的能力。其中&#xff0c;谷歌的机器学习又是怎样的 &#xff1f; 近来机器学习领域实现了很多重大的进展&#xff0c;这些进展让计算机系统具备了解决复杂的真实世界问题的…

安装mysql后在安装目录下只有my-default.ini没有my.ini文件 解决-The MySQL server is running with the --secure-file-priv

WIN10 系统环境 安装mysql后在安装目录下只有my-default.ini没有my.ini文件 。 mysql报错 ---------- The MySQL server is running with the --secure-file-priv option so it cannot execute this statement -------- 但是更改或想要查找配置文件就需要如下操作 在 安装…

loewe测试软件,实测Loewe三角包 最轻的小包最贴心的设计

原标题&#xff1a;实测Loewe三角包 最轻的小包最贴心的设计导语&#xff1a;每周一期的“包治百病”又跟大家见面来啦&#xff01;“包治百病”全方位评测包包的容量、重量、背法、在不同身高妹子身上的效果、各种惊人的小细节以及可能存在的问题&#xff0c;为有意购买这些包…

hadoop集群的搭建(分布式安装)

集群 计算机集群是一种计算机系统&#xff0c;他通过一组松散集成的计算机软件和硬件连接起来高度紧密地协同完成计算工作。集群系统中的单个计算机通常称为节点&#xff0c;通常通过局域网连接。集群技术的特点&#xff1a;1、通过多台计算机完成同一个工作。达到更高的效率 2…

解决:Error establishing a database connection阿里云修改数据库密码

今天闲来无事想把所有的二级密码改成一致的&#xff0c;所以就把阿里云的mysql数据库的密码改了&#xff0c;结果&#xff0c;打开页面报错了&#xff0c;下边的截图是我问题解决后&#xff0c;重新复现的。如果修复这个问题后wordpress登录页面白板&#xff0c;此时不要着急&a…

机器学习各算法思想(极简版)

读到的一篇不错的文章&#xff0c;拿来和大家分享一下。 转自–头条公众号–极数蜗牛 &#xff08;1&#xff09;线性回归 回归最早是由高尔顿研究子女身高与父母身高遗传关系提出的&#xff0c;发现子女平均身高总是向中心回归而得名。其实“一分辛苦一分才”中就蕴含了线性…

斯坦福计算机录取难吗,申请斯坦福究竟有多难? 什么样条件的人才能被斯坦福录取?斯坦福大学直播!...

原标题&#xff1a;申请斯坦福究竟有多难&#xff1f; 什么样条件的人才能被斯坦福录取&#xff1f;斯坦福大学直播&#xff01;申请斯坦福究竟有多难&#xff1f; 什么样条件的人才能被斯坦福录取&#xff1f;斯坦福大学直播&#xff01;西海岸小哈佛之称的斯坦福大学&#xf…

解决:building 'twisted.test.raiser' extension安装scrapy报错

解决&#xff1a;building twisted.test.raiser extension error: Microsoft Visual C 14.0 is required. Get it with "Microsoft Visual C Build Tools": https://visualstudio.microsoft.com/downloads/ 安装scrapy报错&#xff0c;在Twisted安装部分 解决方案…

Linux配置网络出现Eroor adding default gateway的解决方案

最近在学习有关大数据方面的东西&#xff0c;刚开始要搭建模拟的虚拟机集群。用的是Minimal CentOS6.7版本Linux下的系统。因为我要为各个虚拟机设置静态IP&#xff0c;所以就参考网上博客说的进行如下操作: 一、安装完系统后先配置网络&#xff1a; cd /etc/sysconfig/netwo…