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维把所有点分为 ...
随机推荐
- 用dtree实现树形菜单 dtree使用说明
http://www.jb51.net/article/28566.htm 准备工作: 请从脚本之家http://www.jb51.net/jiaoben/31974.html下载dtree.zip文 ...
- sloop公共程序之总体描述
1:功能需求 开发一个公共库文件sloop.c,实现三个常用功能以供其它模块调用.三个功能如下: 功能一:实现一般的信号监听,调用模块只需传入要监听的信号和相应的回调函数就可以在信号到时调用回调函数处 ...
- libevent学习文档(二)eventbase相关接口和参数
Setting up a default event_base The event_base_new() function allocates and returns a new event base ...
- 一元回归_R相关系数_多重检验
sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003& ...
- SSH免密码登录,实现数据传输备份
简单来说,就是通过ssh-keygen -t rsa命令来产生一组公私钥,私钥是id_rsa,公钥是id_rsa.pub,把公钥上传到另一台服务器对应账号的.ssh/authorized_keys,即 ...
- BZOJ2588:LCA+主席树来实现树上两点之间第K大点权查询
对于每个节点维护这个节点到根的权值线段树 对于每个询问(x,y),这条路径上的线段树 tree[x]+tree[y]-tree[lca(x,y)]-tree[fa[lca(x,y)]] #includ ...
- C11线程管理:原子变量&单调函数
1.原子变量 C++11提供了原子类型std::atomic<T>,可以使用任意类型作为模板参数,使用原子变量就不需要使用互斥量来保护该变量,用起来更加简洁. 举个例子,如果要做一个计数器 ...
- C++ Arithmetic Exception
运算异常错误,比如除零错误,浮点数取余等等.
- mysql 导出数据导致锁表
故事原由:今天同事小星做系统优化时问我一个sql问题,为什么查询慢,我看了一眼,发现用到了表A中的datetime类型列进行时间比较,建议他给datetime类型列加上索引. 可这是生产库,表A里面有 ...
- DELPHI中的快捷方式一览(完全版)
1.SHIFT+鼠标左键 先选中任一控件,按键后可选中窗体(选中控件后按Esc效果一样)2.Shift+F8 调试时弹出CPU窗口.3.Shift+F10 等于 ...