给出n个点,每个点坐标为(xi,yi)。
定义距离为D(A,B)=|xA-xB|+|yA-yB|
求每个点到离它最近的点的距离
Input
第一行为一个整数N
接下来N行每行两个整数xi,yi,表示第i个点的坐标
Output
输出N行,每一行为第i个点的最近距离
Sample Input
4
0 0
0 1
1 0
1 1
Sample Output
1
1
1
1
Range
20% 0<N<1001
100% 0<N<200001,0<xi,yi<10,000,001
引用一下http://www.cnblogs.com/snake-hand/archive/2012/08/13/2636236.html
k-d树可以对k维空间进行划分。
这里我们只讨论2维情况,多维的思想类似,实现起来也相差无几。
每次选取一维(最好和之前的维度不同),找到它的中位数,以它为分割线把平面分割成2部分。
然后nth_element()一下,使对于当前维度左边都是比mid值小的,右边大的。
然后就递归
查询的时候要注意,以最近点对为例,
假设由一条竖直的线 . | 目标点在左边,先递归左边找到最近距离S,目标点当前维度坐标+S >分割线,说明右边可能会有一个点使得答案更优。
另外一边同理!
然后,就这道题而言,每个点离它最近的肯定是本身。就找离他最近的2个点,除去本身就是离它最近的点了!
在细节处理上有需要注意的地方,详情参考代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
#include<cstring>
#include<cstdlib>
using namespace std;
const int maxn=200000+20;
const int maxk=5;
int which,K;
int n;
int m;//平面最近m个点
struct Point
{
int x[maxk];
bool operator<(const Point &p)const
{
return x[which]<p.x[which];
}
}x[maxn],aim,pr[maxn];
priority_queue<int>q;//保存最近距离
int ans[5];
int dis(const Point &a,const Point &b)
{
int len=0;
for(int i=0;i<K;i++)len+=abs(a.x[i]-b.x[i]);
return len;
}
void build(int l,int r,int dep)
{
if(l>r)return ;
int mid=(l+r)>>1;
which=dep%K;
nth_element(x+l,x+mid,x+r+1);
build(l,mid-1,dep+1);
build(mid+1,r,dep+1);
}
void query(int l,int r,int dep)
{
if(l>r)return ;
int mid=(l+r)>>1,loc=dep%K;
int len=dis(x[mid],aim);
if(q.size()<m)q.push(len);
else if(len<q.top()){q.pop();q.push(len);}
if(l<r)
{
if(aim.x[loc]<x[mid].x[loc])
{
query(l,mid-1,dep+1);
if(q.size()<m||aim.x[loc]+q.top()>x[mid].x[loc])query(mid+1,r,dep+1);
}
else
{
query(mid+1,r,dep+1);
if(q.size()<m||aim.x[loc]-q.top()<x[mid].x[loc])query(l,mid-1,dep+1);
}
}
}
int main()
{
freopen("find.in","r",stdin);
freopen("find.out","w",stdout);
//转化为求平面最近2个点
K=2;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
for(int j=0;j<K;j++)scanf("%d",&x[i].x[j]);
pr[i]=x[i];
}
build(0,n-1,0);
for(int t=0;t<n;t++)
{
for(int i=0;i<K;i++)aim.x[i]=pr[t].x[i];//x被重新排了序,所以造成了混乱,应该用之前的x
//所以另外开个数组保存
m=2;
while(!q.empty())q.pop();
query(0,n-1,0);
int cnt=0;
while(!q.empty())
{
ans[cnt++]=q.top();
q.pop();
}
printf("%d\n",ans[0]);
}
return 0;
}