K-D Tree

模板:求平面最近点

#include<bits/stdc++.h>
using namespace std;
const long long N=200010,INF=0x3f3f3f3f3f3f3f3f;

inline void upmx(long long &a,const long long b){if(b>a) a=b;}
inline void upmn(long long &a,const long long b){if(b<a) a=b;}
inline void upmn2(long long &a,const long long b,long long id){
    if(b<a) idd=id,a=b;
}

long long D;

struct nd{
    long long id,l,r,mn[2],mx[2],d[2];
    bool operator<(const nd&a)const{
        return d[D]<a.d[D];
    }
}t[N],a[N],now;
long long mn;

inline long long sqr(long long x){
    return x*x;
}

inline long long getdis1(const nd&a,const nd&b){
    return sqr(a.d[0]-b.d[0])+sqr(a.d[1]-b.d[1]);
}

inline long long getdis2(nd&a,nd&b){
    long long d1=max(max(b.mn[0]-a.d[0],a.d[0]-b.mx[0]),0ll);
    long long d2=max(max(b.mn[1]-a.d[1],a.d[1]-b.mx[1]),0ll);
    return d1*d1+d2*d2;
}
void pushup(long long o){
    long long l=t[o].l,r=t[o].r;
    for(long long i=0;i<2;i++){
        t[o].mn[i]=t[o].d[i],t[o].mx[i]=t[o].d[i];
        if(l) upmn(t[o].mn[i],t[l].mn[i]) , upmx(t[o].mx[i],t[l].mx[i]);
        if(r) upmn(t[o].mn[i],t[r].mn[i]) , upmx(t[o].mx[i],t[r].mx[i]);
    }
}

long long build(long long L,long long R,long long d){
    D=d;
    long long M=L+R>>1;
    nth_element(a+L,a+M,a+R+1);
    t[M]=a[M];
    if(L<M) t[M].l=build(L,M-1,d^1);
    if(R>M) t[M].r=build(M+1,R,d^1);
    pushup(M);
    return M;
}
    
void query(long long o){
    if(!o) return;
    if(now.id!=t[o].id) upmn2(mn,getdis1(now,t[o]),t[o].id);
    long long dl=0,dr=0;
    if(t[o].l) dl=getdis2(now,t[t[o].l]);
    if(t[o].r) dr=getdis2(now,t[t[o].r]);
    if(dl<dr){
        if(dl<mn) query(t[o].l);
        if(dr<mn) query(t[o].r);
    }else{
        if(dr<mn) query(t[o].r);
        if(dl<mn) query(t[o].l);
    }
}

long long root,n;

void debug_kdtree(){
    long long n;
    scanf("%lld",&n);
    for(long long i=1;i<=n;i++){
        scanf("%lld%lld",&a[i].d[0],&a[i].d[1]);
        a[i].id=i;
    }
    long long root=build(1,n,0);
    for(long long i=1;i<=n;i++){
        mn=INF;
        now=a[i];
        query(root);
		cout<<mn<<endl;
    }
}


原文地址:https://www.cnblogs.com/lsq647vsejgfb/p/9695893.html