日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2023/12/18 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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(1?≤?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

總結

以上是生活随笔為你收集整理的kd tree学习笔记 (最近邻域查询)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 天天看av| av在线首页 | a级在线看 | 亚洲天堂一区 | 久久精品99久久久 | 中文在线最新版天堂8 | 不许穿内裤随时挨c调教h苏绵 | 精品成人久久 | 亚洲成人午夜电影 | 成人国产欧美 | 国产成人网 | 成人午夜天 | 美女被男人插 | 亚洲欧美精品午睡沙发 | 成人av电影在线播放 | 有机z中国电影免费观看 | av免费看片 | 成人免费自拍视频 | 成人夜色 | 亚洲一区二区观看 | 人人操日日干 | 免费啪啪网 | 国产一级生活片 | 午夜插插插 | 国产盗摄一区二区三区 | 日韩伦理大全 | 精品久久久久久久久久久久久久久久久 | 国产精品一区二区免费在线观看 | 白浆影院 | 69国产精品视频 | 国产精品高清无码 | 欧美一级特黄aaaaaa大片在线观看 | 在线播放国产精品 | 免费观看毛片 | 国产偷拍一区二区 | 亚洲熟妇无码av | 在线成人播放 | 亚洲精品免费在线观看视频 | 91插视频| 久久99国产精品视频 | 国产日韩久久久 | 又粗又大又硬毛片免费看 | 亚洲成av人片在线观看无 | 一级看片免费视频 | 欧美大片黄 | 亚洲国产999 | 国产50页 | 天天干夜夜草 | 国产大片在线观看 | 免费在线观看成人 | 日韩女同互慰一区二区 | 黄色午夜视频 | 色播在线观看 | 人体裸体bbbbb欣赏 | 思思久久久 | av一区二区在线观看 | 欧美高h| 扩阴视频| 一区二区日韩国产 | 一本一本久久a久久精品综合麻豆 | 后进极品美女白嫩翘臀 | 国产人人射 | 欧美第一色| 天堂中文在线8 | 女人脱下裤子让男人桶 | 日日射夜夜操 | 婷婷色九月 | 爱爱免费视频网站 | 亚洲综合图片一区 | 奇米影视一区二区三区 | gav久久| 欧美一区二区在线观看视频 | 91美女片黄在线观看 | 四虎精品欧美一区二区免费 | 欧美中文字幕第一页 | 久久亚洲精品国产精品黑人v | 日本人毛片 | 日韩欧美国产成人 | av55 | 免费高清av在线看 | 色www亚洲国产阿娇yao | 久久久久久久久久久久久久久久久久 | 国产在线黄 | 激情视频在线免费观看 | 国产伦精品一区三区精东 | av毛片在线| 波多野结衣一区二区三区在线 | 久久久这里有精品 | 高清视频免费在线观看 | 欧美 变态 另类 人妖 | 国产女人在线视频 | 少妇熟女视频一区二区三区 | 国产成人无码av在线播放dvd | 噼里啪啦国语版在线观看 | xxxwww在线观看 | www黄色片 | 免费在线性爱视频 | 秋霞影院午夜老牛影院 | 欧美老肥妇做.爰bbww视频 | 污视频免费在线观看网站 |