K-D Tree 学习笔记
又是一个不需要证明的东西,复杂度基本玄学。
具体来说 K-D Tree 是解决高维问题的一个数据结构(其实一般是二维)。
K-D Tree 本质上是一棵二叉搜索树,其的基本思想就是遍历整个状态空间加剪枝。
设问题维度是K,其单次查询的复杂度大概是 \(O(n^{\frac{K-1}{K}})\)。
K-D Tree 的建树方法
我们一般采用每次随机找一个维度,以这个维度排序,且以这个维度的中位数为根的方法。
这种方法基本上不会被卡。
一般来说我们维度的选择就是从 1-K 反复循环进行的。
K-D Tree 的查询方法
这个就具体问题具体分析了,说几个经典问题吧。
最远点
找距离一个坐标最远的点。
这个比较简单,维护每颗子树里每一维最大和最小的值,然后一一配对取最大值就可以了。
最近点
这个就比较妙了。
我们依旧维护每颗子树里每一维最大和最小的值;
然后对于每一维我们找到理想状态下距离最近的点,加入答案中。
其实本质上是 A*。
算了,给个代码实现吧。
int getmin(int rt, int x, int y, int res = 0) {
for(register int i = 0; i < 2; ++i) {
if(i == 1) x = y;
res += max(0, tr[rt].mi[i] - x);
res += max(0, x - tr[rt].mx[i]);
}
return res;
}
K远点
一般来说 K 不会很大。
这个我们可以开个小根堆,初始时堆里有 K 个元素。
查询时每次替换最小的那个就可以了。
动态插入
主要利用的是替罪羊的思想。
插入的话我们直接向平衡树那样插入就可以了。
维护平衡因子,适时推翻重建以维护平衡。
(暂时没有写过)