• 【 HDU2966 】In case of failure(KD-Tree)


    BUPT2017 wintertraining(15) #5E

    HDU - 2966

    题意

    给平面直角坐标系下的n个点的坐标,求离每个点和它最近点的距离的平方。(2 le n le 10^5)

    题解

    这题是裸的kdtree。
    kdtree就是k-dimension tree的缩写,是一种分割k维数据空间的数据结构,可用来多维空间数据的范围搜索和最近邻搜索。
    这题只是求2维的最近的点,代码比较短。以下是我对算法的理解:

    算法过程:

    建树:
    1. 分割区间:区间[L,R],m为中点。当前分割方式为d,d=0,则纵向分割,按x坐标排序,否则横向分割,按y坐标排序。将中位数放在m位置,小于中位数的放在m前面(不必有序),大于中位数的放在后面(不必有序),这一步可以调用stl的nth_element函数。

    2. 递归分割子区间:分割左右子树时d为d^1。

    查询:
    1. 二叉树查找:用a[m]点到p的距离md来更新一下最小距离nd。p.x[i]为第i维的坐标,如果p.x[d]>a[m].x[d],则查询右子树,否则左子树,直到叶子节点。

    2. 回溯:因为最近点未必在p所在的子空间里,因此判断一下p到a[m]所在的分割线的直线距离是否小于当前最小距离nd,若是,则另一半子空间可能存在点距离p更近,于是进入查找。

    其它就是,注意最近点不能是本身,nd初始值为0,nd0则一定要更新,否则若md0则不能拿来更新nd。

    代码

    #include<cstdio>
    #include<algorithm>
    #define N 100005
    #define ll long long
    using namespace std;
    struct point{
    	int x[2];
    }a[N],b[N];
    ll nd;
    int t,n,now;
    bool cmp(point a,point b){return a.x[now] < b.x[now];}
    ll sqr(int x){return (ll)x*x;}
    ll dis(point a,point b){return sqr(a.x[0]-b.x[0])+sqr(a.x[1]-b.x[1]);}
    
    void build(int l,int r,int d){
    	if(l>=r) return;
    	int m=l+r>>1;
    	now=d;
    	nth_element(a+l,a+m,a+r,cmp);
    	build(l,m,d^1);
    	build(m+1,r,d^1);
    }
    void query(int l,int r,int d,point p){
    	if(l>=r)return;
    	int m=l+r>>1,sl=l,sr=m;
    	ll md=dis(a[m],p);
    	if(nd==0||md&&nd>md)nd=md;
    	if(p.x[d]>a[m].x[d])sl=m+1,sr=r;
    	query(sl,sr,d^1,p);
    	if(nd>sqr(a[m].x[d]-p.x[d]))
    		query(l+m+1-sl,m+r-sr,d^1,p);
    }
    int main(){
    	scanf("%d",&t);
    	while(t--){
    		scanf("%d",&n);
    		for(int i=0;i<n;i++)
    			scanf("%d%d",a[i].x,a[i].x+1),b[i]=a[i];
    		build(0,n,0);
    		for(int i=0;i<n;i++)
    			nd=0,query(0,n,0,b[i]),printf("%lld
    ",nd);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    jquery学会的
    oracle技巧-持续更新
    c语言技巧--长期更新
    2019暑假集训 最大子树和
    2019暑假集训 细胞分裂
    2019暑假集训 金明的预算方案
    2019暑假集训 能量项链
    2019暑假集训 神经网络
    0023-特殊的方程
    0022-并联电阻
  • 原文地址:https://www.cnblogs.com/flipped/p/6493340.html
Copyright © 2020-2023  润新知