首页 > 其他分享 >KDTree求平面最近点对

KDTree求平面最近点对

时间:2024-11-12 22:20:05浏览次数:1  
标签:typedef KDTree int long 最近 using 平面 ns define

更新日志

思路

对于每一个点都求一边其最短距离,最后统计。

详细地,对于每个区间,先与其中点判断并更新距离(注意特判不能是同一点),然后找出在这一节点排序维度上,查询点到中点距离,记作 \(D\)。

看查询点在中点左侧/右侧,判断去左右区间。(在这一节点排序的维度上。)

同侧更新完之后,如果一侧的答案要大于当前点到中点的一维距离,就说明答案的另一点可能在另一侧,再查询另一侧的子区间。

模板

struct node{
    int id;
    ll v[K];
    int lson,rson;
}ns[N];
int n;

int ak;
bool cmp(node a,node b){return a.v[ak]<b.v[ak];}

ll dis(int a,int b){
    ll res=0;
    for(int k=0;k<K;k++){
        res+=(ns[a].v[k]-ns[b].v[k])*(ns[a].v[k]-ns[b].v[k]);
    }
    return res;
}
ll dis(int a,int b,int k){
    return (ns[a].v[k]-ns[b].v[k])*(ns[a].v[k]-ns[b].v[k]);
}

int mp[N];

struct kdtree{
    int build(int l,int r,int k=0){
        int m=l+r>>1;
        ak=k;nth_element(ns+l,ns+m,ns+r+1,cmp);
        mp[ns[m].id]=m;
        if(l<m)ns[m].lson=build(l,m-1,(k+1)%K);
        if(m<r)ns[m].rson=build(m+1,r,(k+1)%K);
        return m;
    }
    ll query(int q,int x,int k=0){
        ll res=INF,tes=INF;
        if(x!=q)res=min(res,dis(x,q));
        tes=dis(x,q,k);
        if(ns[q].v[k]<=ns[x].v[k]){
            if(ns[x].lson)res=min(res,query(q,ns[x].lson,(k+1)%K));
            if(tes<res&&ns[x].rson)res=min(res,query(q,ns[x].rson,(k+1)%K));
        }else{
            if(ns[x].rson)res=min(res,query(q,ns[x].rson,(k+1)%K));
            if(tes<res&&ns[x].lson)res=min(res,query(q,ns[x].lson,(k+1)%K));
        }
        return res;
    }
}kdt;

例题

HDU2966

代码

前注:就是模板。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef __int128 i128;
typedef double db;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<int,ll> pil;
typedef pair<ll,int> pli;
template <typename Type>
using vec=vector<Type>;
template <typename Type>
using grheap=priority_queue<Type>;
template <typename Type>
using lrheap=priority_queue<Type,vector<Type>,greater<Type> >;
#define fir first
#define sec second
#define pub push_back
#define pob pop_back
#define puf push_front
#define pof pop_front
#define dprint(x) cout<<#x<<"="<<x<<"\n";

const int inf=0x3f3f3f3f;
const ll INF=4e18;
const int mod=1e9+7/*998244353*/;

const int N=1e5+5,K=2;

struct node{
    int id;
    ll v[K];
    int lson,rson;
}ns[N];
int n;

int ak;
bool cmp(node a,node b){return a.v[ak]<b.v[ak];}

ll dis(int a,int b){
    ll res=0;
    for(int k=0;k<K;k++){
        res+=(ns[a].v[k]-ns[b].v[k])*(ns[a].v[k]-ns[b].v[k]);
    }
    return res;
}
ll dis(int a,int b,int k){
    return (ns[a].v[k]-ns[b].v[k])*(ns[a].v[k]-ns[b].v[k]);
}

int mp[N];

struct kdtree{
    int build(int l,int r,int k=0){
        int m=l+r>>1;
        ak=k;nth_element(ns+l,ns+m,ns+r+1,cmp);
        mp[ns[m].id]=m;
        if(l<m)ns[m].lson=build(l,m-1,(k+1)%K);
        if(m<r)ns[m].rson=build(m+1,r,(k+1)%K);
        return m;
    }
    ll query(int q,int x,int k=0){
        ll res=INF,tes=INF;
        if(x!=q)res=min(res,dis(x,q));
        tes=dis(x,q,k);
        if(ns[q].v[k]<=ns[x].v[k]){
            if(ns[x].lson)res=min(res,query(q,ns[x].lson,(k+1)%K));
            if(tes<res&&ns[x].rson)res=min(res,query(q,ns[x].rson,(k+1)%K));
        }else{
            if(ns[x].rson)res=min(res,query(q,ns[x].rson,(k+1)%K));
            if(tes<res&&ns[x].lson)res=min(res,query(q,ns[x].lson,(k+1)%K));
        }
        return res;
    }
}kdt;

void solve(){
    cin>>n;
    for(int i=1;i<=n;i++){
        ns[i].id=i;
        cin>>ns[i].v[0]>>ns[i].v[1];
        ns[i].lson=ns[i].rson=0;
    }
    int rt=kdt.build(1,n);
    for(int i=1;i<=n;i++){
        cout<<kdt.query(mp[i],rt)<<"\n";
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int t;cin>>t;
    while(t--)solve();
    return 0;
}

标签:typedef,KDTree,int,long,最近,using,平面,ns,define
From: https://www.cnblogs.com/HarlemBlog/p/18542782

相关文章