hdu4347
求与询问点欧几里德距离前m小的点
其实就是在kdtree询问的时候用优先队列维护一下就好了
好久没写kdtree练一练,注意这道题是多测
#include<bits/stdc++.h> using namespace std;
const int inf=1e4+;
int key,root,n,m,q,k,mxd;
int sqr(int x)
{
return x*x;
} struct point
{
int d[];
friend int dis(point a,point b)
{
int s=;
for (int i=; i<k; i++)
s+=sqr(a.d[i]-b.d[i]);
return s;
}
} po; struct node
{
point nw;
int son[],mi[],mx[];
friend bool operator <(node a,node b)
{
return a.nw.d[key]<b.nw.d[key];
}
}; struct li
{
point a; int l;
friend bool operator <(li a, li b)
{
return a.l<b.l;
}
} mx;
set<li> st; struct kdtree
{
node a[];
void init()
{ a[].son[]=a[].son[]=;
for (int i=; i<; i++)
{
a[].mx[i]=-inf;
a[].mi[i]=inf;
}
}
void update(int x)
{
int l=a[x].son[],r=a[x].son[];
for (int i=; i<k; i++)
{
a[x].mi[i]=min(a[x].nw.d[i],min(a[l].mi[i],a[r].mi[i]));
a[x].mx[i]=max(a[x].nw.d[i],max(a[l].mx[i],a[r].mx[i]));
}
}
int build(int l,int r,int cur)
{
if (l>r) return ;
int m=(l+r)>>;
key=cur; nth_element(a+l,a+m,a+r+);
a[m].son[]=build(l,m-,(cur+)%k);
a[m].son[]=build(m+,r,(cur+)%k);
update(m);
return m;
}
int getmi(int x)
{
int s=;
for (int i=; i<k; i++)
s+=sqr(max(po.d[i]-a[x].mx[i],)+max(a[x].mi[i]-po.d[i],));
return s;
}
void ask(int q)
{
if (!q) return;
int tmp=dis(a[q].nw,po);
st.insert((li){a[q].nw,tmp});
if (st.size()>m)
{
set<li>::iterator it=st.end(); it--;
st.erase(it);
}
mxd=(*st.rbegin()).l;
int l=a[q].son[],r=a[q].son[],dl=,dr=;
if (l) dl=getmi(l);
if (r) dr=getmi(r);
if (dl<dr)
{
if (dl<mxd||st.size()<m) ask(l);
if (dr<mxd||st.size()<m) ask(r);
}
else {
if (dr<mxd||st.size()<m) ask(r);
if (dl<mxd||st.size()<m) ask(l);
}
}
} kd; int main()
{
while (scanf("%d%d",&n,&k)!=EOF)
{
kd.init();
for (int i=; i<=n; i++)
for (int j=; j<k; j++)
scanf("%d",&kd.a[i].nw.d[j]);
root=kd.build(,n,);
scanf("%d",&q);
while (q--)
{
for (int i=; i<k; i++)
scanf("%d",&po.d[i]);
scanf("%d",&m);
st.clear();
kd.ask(root);
printf("the closest %d points are:\n",m);
for (set<li>::iterator it=st.begin(); it!=st.end(); it++)
{
point ans=(*it).a;
for (int i=; i<k; i++)
{
printf("%d",ans.d[i]);
if (i!=k-) printf(" "); else puts("");
}
}
}
}
}
hdu4347的更多相关文章
- 【hdu4347】The Closest M Points 【KD树模板】
题意 一个k维空间,给出n个点的坐标,给出t个询问,每个询问给出一个点的坐标和一个m.对于每个询问找出跟这个点最接近的m个点 分析 kd树的模板题. #include <cstdio> # ...
- [hdu4347]The Closest M Points(平衡树式kdtree)
解题关键:模板题(结合起来了) #include<iostream> #include<cstdio> #include<cstring> #include< ...
- [hdu4347]The Closest M Points(线段树形式kd-tree)
解题关键:kdtree模板题,距离某点最近的m个点. #include<cstdio> #include<cstring> #include<algorithm> ...
- 【kd-tree】专题总结
感谢orz神·小黑的指导 kd-tree就是用来计算若干维空间k近/远点的数(shou)据(suo)结(you)构(hua) 建树 假设题目是k维的点 第deep层就是用deep%k+1维把所有点分为 ...
随机推荐
- android adb devices 后出现offline问题的解决
Android在使用adb 命令时有时会发现设备的状态是offline,我的神呀,这怎么让我们调试呢.必须解决这个问题. 解决方式如下: 以下方法请确保你的设备处于调试模式下. 方法一:执行 #adb ...
- Linux应用编程之串口操作20170901
主要介绍在Linux应用程序下对串口的操作: 1.串口初始化 int InitCom() { int Ret; Ret = SerailComm.OpenCom( ComPortDevPath, 0 ...
- _MSC_VER
https://msdn.microsoft.com/en-us/library/vstudio/b0084kay.aspx Evaluates to an integer literal that ...
- C# 利用mysql.data 在mysql中创建数据库及数据表
C# 利用mysql.data 在mysql中创建数据库及数据表 using System; using System.Collections.Generic; using System.Linq; ...
- Spring MVC同时接收一个对象与List集合对象
原:https://blog.csdn.net/u011781521/article/details/77586688/ Spring MVC同时接收一个对象与List集合对象 2017年08月25日 ...
- Python基础之面向对象(进阶篇)
面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使用(可以讲多函数中公用的变量封装到对象中) 对象,根据模板创建的实例(即:对象),实 ...
- 深入分析Java中的 == 和equals
关于Java中的 == 和equals的解释请看这位博主的文章 :http://www.cnblogs.com/dolphin0520/p/3592500.html 以下是我对这篇文章的一些扩展. 对 ...
- 基于javaWeb阶段下的Servlet总结
1. Servlet概述 Servlet是用Java语言编写的服务端的程序,采用request--response模式提供Web服务,并且支持标准ServletAPI,Servlet就一个运行在w ...
- ZOJ 3787 Access System 水
LINK:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3787 思路:结构体 时间转化为秒记录下最小并且排序就好了 /** ...
- 如何用jQuery封装插件
引子 现在网上关于js和jquery封装的插件很多,我刚刚接触前端的时候,就很敬佩那些自己写插件的大牛们!因为是他们给网站开发更多的便利,很多网页效果,网上很多现成的插件!那么这些插件是如何写的呢?首 ...