正题
翻译过来就是 k维的树,很显然就可以看出它是一个高维数据结构。
因为它高维,所以它的局限性就比线段树要小很多。
一般可以做k维空间的信息,比如三维最近点对,之类的。
它使用一个二叉搜索树来维护的,每一维排序的关键字是循环的,比如说第一层按照第一维来排,第二层按照第二维来拍,...,第k层按照第k维来排,第(k+1)层按照第1维来排。
然后访问空间信息的时候就可以在上面做一些剪枝优化,一般的,一颗维护K维空间的KDT每次查询的时间是。
然后代码也十分简短:
以[国家集训队]JZPFAR为例,注意打kdt查询的时候尽量把能加上的优化都加上,尽管不是那么显然的优化,有时候10->100就靠它了。
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int n,rt,num=0,m;
int sx,sy;
struct node{
int x,y,id;
}s[N];
struct Heap{
int x;
long long dis;
bool operator<(const Heap q)const{
return dis!=q.dis?dis>q.dis:x<q.x;
}
};
priority_queue<Heap> q;
struct KDT{
int x0,y0,x1,y1;
node p;
int ls,rs;
}T[N];
long long get_dis(node a){return 1ll*(sx-a.x)*(sx-a.x)+1ll*(sy-a.y)*(sy-a.y);}
bool cmp1(node x,node y){return x.x<y.x;}
bool cmp2(node x,node y){return x.y<y.y;}
void read(int&x){
char ch=getchar();x=0;
bool tf=false;
while(ch<'0' || ch>'9') ch=='-'?tf=true:0,ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
tf?x=-x:0;
}
int build(int l,int r,int type){
int xmin=1e9,ymin=1e9,xmax=-1e9,ymax=-1e9;
for(int i=l;i<=r;i++){
xmin=min(xmin,s[i].x),xmax=max(xmax,s[i].x);
ymin=min(ymin,s[i].y),ymax=max(ymax,s[i].y);
}
int mid=(l+r)/2,now=++num;
nth_element(s+1+l,s+1+mid,s+1+r,type?cmp1:cmp2);
T[now]=(KDT){xmin,ymin,xmax,ymax,s[mid],0,0};
if(l<mid) T[now].ls=build(l,mid-1,type^1);
if(mid<r) T[now].rs=build(mid+1,r,type^1);
return now;
}
long long max_dis(int now){
if(!now) return -10;
return max(max(get_dis((node){T[now].x0,T[now].y0}),get_dis((node){T[now].x0,T[now].y1}))
,max(get_dis((node){T[now].x1,T[now].y0}),get_dis((node){T[now].x1,T[now].y1})));
}
void query(int now){
long long res=get_dis(T[now].p);
if(res>q.top().dis || (res==q.top().dis && T[now].p.id<q.top().x))
q.pop(),q.push((Heap){T[now].p.id,res});
long long D1=max_dis(T[now].ls),D2=max_dis(T[now].rs);
if(D1>D2){
if(D1>=q.top().dis) query(T[now].ls);
if(D2>=q.top().dis) query(T[now].rs);
}
else{
if(D2>=q.top().dis) query(T[now].rs);
if(D1>=q.top().dis) query(T[now].ls);
}
}
int main(){
read(n);
int x,y,k;
for(int i=1;i<=n;i++) read(s[i].x),read(s[i].y),s[i].id=i;
rt=build(1,n,0);
read(m);
while(m--){
read(x);read(y);read(k);sx=x,sy=y;k=abs(k);
while(!q.empty()) q.pop();
for(int i=1;i<=k;i++) q.push((Heap){-1,-1});
query(rt);
printf("%d\n",q.top().x);
}
}
本文深入探讨了K-D树这一高效的数据结构,详细介绍了其在高维空间中的应用,如三维最近点对查找等。通过二叉搜索树的形式,K-D树能够循环地按不同维度进行排序,实现对空间信息的有效查询与剪枝优化。文章提供了具体实例和简洁的代码实现,展示了K-D树在实际问题解决中的强大能力。
789

被折叠的 条评论
为什么被折叠?



