Hdu 2966 In case of failure kd-tree模板题

参考博客
http://www.cnblogs.com/LyonLys/archive/2013/05/26/hdu_2966_Lyon.html
kd-tree的理解可以参见百度百科:
http://baike.baidu.com/link?url=tBsrmpSUW9V0qcVCzBCM52ZLqN8s7NaRV89a2DJhU-pOttVq2u29Gw7Rt4CoFL6RN9sJ2VnvsLtD5yvDp3xljq

//题意:给定n个点,查找n个点所对应的最近点的距离的平方。
// E - In case of failure HDU - 2966
// kd-tree
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<iostream>
#include<queue>
#include<stack>
#include<cmath>
#include<cstring>
using namespace std;

const int maxn=100000+100;
typedef long long LL;
struct Point{
    int x[2];
};
Point po[maxn],ori[maxn];
int cur,dim;

bool cmp(Point a,Point b)
{
    return a.x[cur]<b.x[cur];
}

int n,ans;

void build(int L,int R,int depth)
{
    if(L>=R)    return;
    int M=(L+R)>>1;
    cur=depth%dim;
    nth_element(po+L,po+M,po+R+1,cmp);
    build(L,M-1,depth+1);
    build(M+1,R,depth+1);
}

const LL INF=2*1e18;
LL sqr(int x)
{
    return 1LL*x*x;
}
LL dist(Point a,Point b)
{
    LL res=0;
    for(int i=0;i<dim;i++){
        res+=sqr(a.x[i]-b.x[i]);
    }
    return res?res:INF;
}
LL find(Point x,int L,int R,int depth)
{
    int cur=depth%dim;
    if(L>=R){
        if(L==R)    return dist(x,po[L]);
        else        return INF;
    }
    int M=(L+R)>>1;
    LL res=dist(x,po[M]);
    LL tmp;
    if(x.x[cur]<po[M].x[cur]){
        tmp=find(x,L,M-1,depth+1);
        if(tmp>sqr(x.x[cur]-po[M].x[cur])){
            tmp=min(tmp,find(x,M+1,R,depth+1));
        }

    }
    else{
        tmp=find(x,M+1,R,depth+1);
        if(tmp>sqr(x.x[cur]-po[M].x[cur])){
            tmp=min(tmp,find(x,L,M-1,depth+1));
        }
    }
    return min(res,tmp);
}
void solve()
{
    scanf("%d",&n);
    int x,y;
    for(int i=1;i<=n;i++){
        scanf("%d %d",&x,&y);
        po[i].x[0]=x;
        po[i].x[1]=y;
        ori[i]=po[i];
    }
    cur=0;
    dim=2;
    build(1,n,0);
    for(int i=1;i<=n;i++){
        printf("%lld\n",find(ori[i],1,n,0));
    }

}

int main()
{

    int T;
    scanf("%d",&T);
    while(T--){
        solve();
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值