hdu 4347 The Closest M Points (kd树)

hdu 4347

题意:

  求k维空间中离所给点最近的m个点,并按顺序输出  。

解法:

  kd树模板题 。

  不懂kd树的可以先看看这个

  不多说,上代码 。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cmath>
  5 #include <cstring>
  6 #include <queue>
  7 #include <set>
  8 #include <vector>
  9 #include <map>
 10 #define ll long long
 11
 12 using namespace std;
 13
 14 const int N=50007;
 15 const int K=6;
 16
 17 int n,m;
 18
 19 struct point{
 20     int a[K];
 21     int div;  // 按哪个维度划分
 22     bool lef;  // 是否是叶子节点
 23     ll dis;  // 离询问点的距离。注意这个在读入建树时不会用到,在进入队列时才用到
 24     void print(){
 25         printf("%d",a[0]);
 26         for (int i=1;i<m;i++)
 27             printf(" %d",a[i]);
 28         puts("");
 29     }
 30     bool operator < (const point &t) const{
 31         return dis<t.dis;
 32     }
 33     point(){}
 34     point(point &t,ll d){
 35         for (int i=0;i<m;i++) a[i]=t.a[i];
 36         dis=d;
 37     }
 38 }p[N],tar;
 39
 40 int cmp_NO;
 41 inline bool cmp(point x,point y){
 42     return x.a[cmp_NO]<y.a[cmp_NO];
 43 }
 44
 45 inline ll dis(point x,point y){
 46     ll ret=0;
 47     for (int i=0;i<m;i++)
 48         ret+=(x.a[i]-y.a[i])*(x.a[i]-y.a[i]);
 49     return ret;
 50 }
 51
 52 inline void bulid_kdt(int L,int R,int d){
 53     if (L>R) return;
 54     int mid=(L+R)>>1;
 55     cmp_NO=d;
 56     nth_element(p+L,p+mid,p+R+1,cmp);
 57     p[mid].div=d;
 58     if (L==R){
 59         p[L].lef=true;
 60         return;
 61     }
 62     bulid_kdt(L,mid-1,(d+1)%m);
 63     bulid_kdt(mid+1,R,(d+1)%m);
 64 }
 65
 66 priority_queue<point> que;
 67 int num,nownum;
 68 ll ans;
 69
 70 inline void find_kd(int L,int R){
 71     if (L>R) return;
 72
 73     int mid=(L+R)>>1;
 74     ll d=dis(p[mid],tar);
 75     if (p[mid].lef){
 76         if (nownum<num){
 77             nownum++;
 78             que.push(point(p[mid],d));
 79             ans=max(ans,d);
 80         }
 81         else if (ans>d){
 82             que.pop();
 83             que.push(point(p[mid],d));
 84             ans=que.top().dis;
 85         }
 86         return;
 87     }
 88
 89     int t=tar.a[p[mid].div]-p[mid].a[p[mid].div];
 90     if (t>0){
 91         find_kd(mid+1,R);
 92         if (nownum<num){
 93             nownum++;
 94             que.push(point(p[mid],d));
 95             ans=max(ans,d);
 96             find_kd(L,mid-1);
 97         }
 98         else {
 99             if (ans>d){
100                 que.pop();
101                 que.push(point(p[mid],d));
102                 ans=que.top().dis;
103             }
104             if (ans>t*t)
105                 find_kd(L,mid-1);
106         }
107     }
108     else {
109         find_kd(L,mid-1);
110         if (nownum<num){
111             nownum++;
112             que.push(point(p[mid],d));
113             ans=max(ans,d);
114             find_kd(mid+1,R);
115         }
116         else{
117             if (ans>d){
118                 que.pop();
119                 que.push(point(p[mid],d));
120                 ans=que.top().dis;
121             }
122             if (ans>t*t)
123                 find_kd(mid+1,R);
124         }
125     }
126 }
127
128 inline void put(){
129     if (que.empty()) return;
130     point pp=que.top();
131     que.pop();
132     put();
133     pp.print();
134 }
135
136 int main(){
137     while (~scanf("%d%d",&n,&m)){
138         for (int i=0;i<n;i++){
139             for (int j=0;j<m;j++)
140                 scanf("%d",&p[i].a[j]);
141             p[i].lef=false;
142         }
143
144         bulid_kdt(0,n-1,0);  // 这一步相当于将原数组重新排了个序,先访问到的点放在中间
145
146         int q;
147         scanf("%d",&q);
148         while (q--){
149             for (int i=0;i<m;i++)
150                 scanf("%d",&tar.a[i]);
151             while (!que.empty()) que.pop();
152             scanf("%d",&num);
153             nownum=0;
154             ans=-1;
155             find_kd(0,n-1);
156             printf("the closest %d points are:\n",num);
157             put();
158         }
159     }
160     return 0;
161 }
时间: 2024-12-27 17:02:56

hdu 4347 The Closest M Points (kd树)的相关文章

bzoj 3053 HDU 4347 : The Closest M Points kd树

bzoj 3053 HDU 4347 : The Closest M Points  kd树 题目大意:求k维空间内某点的前k近的点. 就是一般的kd树,根据实测发现,kd树的两种建树方式,即按照方差较大的维度分开(建树常数大)或者每一位轮换分割(询问常数大),后者更快也更好些,以后就果断写第二种了. #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using

数据结构(KD树):HDU 4347 The Closest M Points

The Closest M Points Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 98304/98304 K (Java/Others)Total Submission(s): 3285    Accepted Submission(s): 1201 Problem Description The course of Software Design and Development Practice is objection

HDU 4347 - The Closest M Points - [KDTree模板题]

本文参考: https://www.cnblogs.com/GerynOhenz/p/8727415.html kuangbin的ACM模板(新) 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4347 Problem Description The course of Software Design and Development Practice is objectionable. ZLC is facing a serious problem

The Closest M Points//kd树+优先队列

题目 The Closest M Points Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 98304/98304 K (Java/Others) Total Submission(s): 7570 Accepted Submission(s): 2378 Problem Description The course of Software Design and Development Practice is objectionab

HDU 4347 The Closest M Points (kdTree)

赤果果的kdTree. 传送门:http://www.cnblogs.com/v-July-v/archive/2012/11/20/3125419.html 其实就是二叉树的变形 #include<bits/stdc++.h> using namespace std; const int maxn = 5e4+6,K = 5; #define squ(x) ((x)*(x)) int k,n,idx; struct Point { int x[K]; bool operator <(c

【HDOJ】4347 The Closest M Points

居然是KD解. 1 /* 4347 */ 2 #include <iostream> 3 #include <sstream> 4 #include <string> 5 #include <map> 6 #include <queue> 7 #include <set> 8 #include <stack> 9 #include <vector> 10 #include <deque> 11 #i

K-D树问题 HDU 4347

K-D树可以看看这个博客写的真心不错!这里存个版 http://blog.csdn.net/zhjchengfeng5/article/details/7855241 HDU 4349 #include <map> //KD树学习http://blog.csdn.net/zhjchengfeng5/article/details/7855241 #include <set> #include <list> #include <cmath> #include

【hdu4347】The Closest M Points 【KD树模板】

题意 一个k维空间,给出n个点的坐标,给出t个询问,每个询问给出一个点的坐标和一个m.对于每个询问找出跟这个点最接近的m个点 分析 kd树的模板题. 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <queue> 6 7 using namespace std; 8 typedef long long

HDU 5992 Finding Hotels(KD树)题解

题意:n家旅店,每个旅店都有坐标x,y,每晚价钱z,m个客人,坐标x,y,钱c,问你每个客人最近且能住进去(非花最少钱)的旅店,一样近的选排名靠前的. 思路:KD树模板题 代码: #include<set> #include<map> #include<stack> #include<cmath> #include<queue> #include<vector> #include<cstdio> #include<c