求与询问点欧几里德距离前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的更多相关文章

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

    题意 一个k维空间,给出n个点的坐标,给出t个询问,每个询问给出一个点的坐标和一个m.对于每个询问找出跟这个点最接近的m个点 分析 kd树的模板题. #include <cstdio> # ...

  2. [hdu4347]The Closest M Points(平衡树式kdtree)

    解题关键:模板题(结合起来了) #include<iostream> #include<cstdio> #include<cstring> #include< ...

  3. [hdu4347]The Closest M Points(线段树形式kd-tree)

    解题关键:kdtree模板题,距离某点最近的m个点. #include<cstdio> #include<cstring> #include<algorithm> ...

  4. 【kd-tree】专题总结

    感谢orz神·小黑的指导 kd-tree就是用来计算若干维空间k近/远点的数(shou)据(suo)结(you)构(hua) 建树 假设题目是k维的点 第deep层就是用deep%k+1维把所有点分为 ...

随机推荐

  1. 【单调栈】【CF5E】 Bindian Signalizing

    传送门 Description 给你一个环,环上有一些点,点有点权.定义环上两点能相互看见当且仅当两点间存在一个弧使得弧上不存在一个点的点权大于着两个点.求一共有多少个点能互相看到 Input 第一行 ...

  2. Python3 字典 get() 方法

     Python3 字典 描述 Python 字典 get() 函数返回指定键的值,如果值不在字典中返回默认值. 语法 get()方法语法: dict.get(key, default=None) 参数 ...

  3. 【题解】Popping Balls AtCoder Code Festival 2017 qual B E 组合计数

    蒟蒻__stdcall终于更新博客辣~ 一下午+一晚上=一道计数题QAQ 为什么计数题都这么玄学啊QAQ Prelude 题目链接:这里是传送门= ̄ω ̄= 下面我将分几个步骤讲一下这个题的做法,大家不 ...

  4. apk签名验证机制

    声明: 1.本帖转载自:http://riusksk.blogbus.com/logs/272154406.html,仅供自用,勿喷 2.欢迎交流学习 签名后的APK,在/META-INF目录下会生成 ...

  5. k8s本地搭建相信步骤

    搭建前的准备: 主机名配置 cat >/etc/hosts<<EOF127.0.0.1 localhost localhost.localdomain localhost4 loca ...

  6. 轮廓问题/Outline Problem-->改进的算法及时间复杂度分析

    前面写过一篇关于轮廓算法的文章,是把合并建筑和合并轮廓是分开对待的,并且为了使轮廓合并的时候算法简单,对x坐标使用了double类型,然后对整形的x坐标数据进行合并.这样做是为了使得需找拐点的算法容易 ...

  7. tf.transpose函数解析

    tf.transpose函数解析 觉得有用的话,欢迎一起讨论相互学习~Follow Me tf.transpose(a, perm = None, name = 'transpose') 解释 将a进 ...

  8. shell多进程的实现

    需求:多个脚本彼此互不干涉,同时运行,节省时间 菜鸟级实现: #!/bin/sh dir="/data/test" $dir/sbin/test1.sh >> $dir ...

  9. Latent Semantic Analysis(LSA/ LSI)原理简介

    LSA的工作原理: How Latent Semantic Analysis Works LSA被广泛用于文献检索,文本分类,垃圾邮件过滤,语言识别,模式检索以及文章评估自动化等场景. LSA其中一个 ...

  10. Anniversary party(树形dp入门)

    Anniversary party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...