版权声明:本文为博主原创文章,未经博主允许不得转载。

hdu 4347

题意:

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

解法:

  kd树模板题 。

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

  不多说,上代码 。

 #include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <map>
#define ll long long using namespace std; const int N=;
const int K=; int n,m; struct point{
int a[K];
int div; // 按哪个维度划分
bool lef; // 是否是叶子节点
ll dis; // 离询问点的距离。注意这个在读入建树时不会用到,在进入队列时才用到
void print(){
printf("%d",a[]);
for (int i=;i<m;i++)
printf(" %d",a[i]);
puts("");
}
bool operator < (const point &t) const{
return dis<t.dis;
}
point(){}
point(point &t,ll d){
for (int i=;i<m;i++) a[i]=t.a[i];
dis=d;
}
}p[N],tar; int cmp_NO;
inline bool cmp(point x,point y){
return x.a[cmp_NO]<y.a[cmp_NO];
} inline ll dis(point x,point y){
ll ret=;
for (int i=;i<m;i++)
ret+=(x.a[i]-y.a[i])*(x.a[i]-y.a[i]);
return ret;
} inline void bulid_kdt(int L,int R,int d){
if (L>R) return;
int mid=(L+R)>>;
cmp_NO=d;
nth_element(p+L,p+mid,p+R+,cmp);
p[mid].div=d;
if (L==R){
p[L].lef=true;
return;
}
bulid_kdt(L,mid-,(d+)%m);
bulid_kdt(mid+,R,(d+)%m);
} priority_queue<point> que;
int num,nownum;
ll ans; inline void find_kd(int L,int R){
if (L>R) return; int mid=(L+R)>>;
ll d=dis(p[mid],tar);
if (p[mid].lef){
if (nownum<num){
nownum++;
que.push(point(p[mid],d));
ans=max(ans,d);
}
else if (ans>d){
que.pop();
que.push(point(p[mid],d));
ans=que.top().dis;
}
return;
} int t=tar.a[p[mid].div]-p[mid].a[p[mid].div];
if (t>){
find_kd(mid+,R);
if (nownum<num){
nownum++;
que.push(point(p[mid],d));
ans=max(ans,d);
find_kd(L,mid-);
}
else {
if (ans>d){
que.pop();
que.push(point(p[mid],d));
ans=que.top().dis;
}
if (ans>t*t)
find_kd(L,mid-);
}
}
else {
find_kd(L,mid-);
if (nownum<num){
nownum++;
que.push(point(p[mid],d));
ans=max(ans,d);
find_kd(mid+,R);
}
else{
if (ans>d){
que.pop();
que.push(point(p[mid],d));
ans=que.top().dis;
}
if (ans>t*t)
find_kd(mid+,R);
}
}
} inline void put(){
if (que.empty()) return;
point pp=que.top();
que.pop();
put();
pp.print();
} int main(){
while (~scanf("%d%d",&n,&m)){
for (int i=;i<n;i++){
for (int j=;j<m;j++)
scanf("%d",&p[i].a[j]);
p[i].lef=false;
} bulid_kdt(,n-,); // 这一步相当于将原数组重新排了个序,先访问到的点放在中间 int q;
scanf("%d",&q);
while (q--){
for (int i=;i<m;i++)
scanf("%d",&tar.a[i]);
while (!que.empty()) que.pop();
scanf("%d",&num);
nownum=;
ans=-;
find_kd(,n-);
printf("the closest %d points are:\n",num);
put();
}
}
return ;
}

最新文章

  1. linux 代码分析工具 gprof - 以wpa_supplicant为例
  2. android Spinner的简单用法
  3. Laravel 5.x 启动过程分析 [转]
  4. python第一天基础1-2
  5. oracle学习笔记系列------oracle 基本操作之基本函数的用法
  6. [部署]MVC4.0+EF5.0+ODT+ORACLE相关注意事项
  7. jQuery操作DOM和CSS函数
  8. poj 1386 Play on Words 有向欧拉回路
  9. poj 3903 Stock Exchange(最长上升子序列,模版题)
  10. 洛谷P1120 小木棍
  11. Unity3d在安卓android的更新(APK覆盖)
  12. js变量,语句
  13. 【2017集美大学1412软工实践_助教博客】团队作业5——测试与发布(Alpha版本)
  14. 关于VS2017+Qt5.6.3(msvc2015_64)联合编程Qt project settings界面没有ok,cancel选项的问题
  15. 智联python 技能摘取
  16. Confluence 6 修改警告的阈值和表现
  17. Codeforces 825E Minimal Labels - 拓扑排序 - 贪心
  18. oracle 如何查看oracle数据库版本
  19. Java代码优化(一)
  20. python GIL(Global Interpreter Lock)

热门文章

  1. 深入理解JVM一垃圾回收算法
  2. a++ 和 ++a 的区别
  3. 【BZOJ4405】【WC2016】挑战NPC(带花树)
  4. 洛谷 P3723 [AH2017/HNOI2017]礼物 解题报告
  5. linux内核分析 第三周 构造一个简单的Linux系统MenuOS
  6. 【组合数学】【P4996】 咕咕咕
  7. 解析C#彩色图像灰度化算法的实现代码详解
  8. HDU--2722
  9. 解决SQL Server 2008 64位系统无法导入Access/Excel的问题
  10. UVA 1650 Number String