应用于K维数据的快速查找,比如横坐标,纵坐标,价格……,本模板以16青岛区域赛K题为例 —— 三维K - D Tree 模板 我们应该都见过平衡树吧,那就是1-D树,变成k维之后,我们连续分割1 - k维,然后继续分割,实现快速查找,画图的时候就能够理解这个数据结构了 n个旅馆 x,y,csot m个用户 x,y,limitcost 问你每个用户在可以接受的价格内距离最近的旅馆是哪个 #define deep 3 // K-D树的维度 #define inf (1e18) //用ll防止开根号,造成浮点误差 using namespace std; typedef long long ll; const int maxn = 2e5+2e3; int retid;//最优的旅馆选择编号 ll ans;//判断距离最小值 int loc;//当前进行的维度 int n,m;//n个旅馆,m个顾客 struct node{ int id; int data[deep]; //对各个维度都从小到大排序 bool operator < (const node &b) const{ if(data[loc] < b.data[loc]) return 1; return 0; } }P[maxn],tmp[maxn],Now,Aim;//P数组排序,tmp数组副本作为输出 void creat_KDtree(int l,int r,int flor){ if(l >= r){ return; } int mid = (l + r) >> 1; loc = flor % deep; nth_element(P+l,P+mid,P+r+1); /*把p+mid元素放在中间位置,使其左边元素比它小,右边比它大 nth_element(first,nth,last) first,last 第一个和最后一个迭代器,也可以直接用数组的位置。 nth,要定位的第n个元素,能对它进行随机访问. 将第n_th元素放到它该放的位置上,左边元素都小于它,右边元素都大于它.*/ creat_KDtree(l,mid-1,flor+1); creat_KDtree(mid+1,r,flor+1); } void judge(int x)//根据题意的判断函数{ Now = P[x]; if(Now.data[2] > Aim.data[2]) return; ll dis = (Now.data[0] - Aim.data[0]) * (Now.data[0] - Aim.data[0]) + (Now.data[1] - Aim.data[1]) * (Now.data[1] - Aim.data[1]); if(dis < ans || dis == ans && Now.id < retid){ ans = dis; retid = Now.id; } } void Find(int l,int r,int flor)//也是根据题意来写{ loc = flor % deep; if(l >= r){ if(l == r) judge(l); return; } int mid = (l + r) >> 1; judge(mid); Now = P[mid]; if(loc == 2){ if(Now.data[loc] >= Aim.data[loc]) Find(l,mid-1,flor+1); else{ Find(l,mid-1,flor+1); Find(mid+1,r,flor+1); } } else{ int len = Now.data[loc] - Aim.data[loc]; if(len >= 0){ Find(l,mid-1,flor+1); if(((ll)len * len) < ans){ Find(mid+1,r,flor+1); } } else{ Find(mid+1,r,flor+1); if(((ll)len * len) < ans){ Find(l,mid-1,flor+1); } } } }