KDT学习笔记
KDT处理的一些问题:给你一个 \(k\) 维空间,\(n\) 个点,每次查询一个超矩形,求这个超矩形里面包含的点的信息,以下默认 \(k=2\)。
建树
重复以下流程:
- 轮流选择 \(k\) 维作为划分依据。
- 选择第 \(k\) 维里的中位数作为根。
求中位数的过程是 \(O(n)\) 的,每次划分数据规模都会 \(/2\),所以建树总时间复杂度为 \(O(n\log n)\)。
查询
KDT的重点。
如果查询的超矩形和当前划分出的超矩形无交,那么直接返回。
如果查询的超矩形包含当前划分出的超矩形,直接返回矩形信息。
如果查询的超矩形部分包含当前划分出的超矩形,我们考虑超矩形的一条边,这条边最多只能穿过当前划分出的超矩形的两个孙子节点,另外的两个要么被包含,要么不交。
根据这个可以写出:\(T(n)=2(\frac T4)+O(1)\) ,总时间复杂度就是 \(O(\sqrt n)\)。
插入
我们发现KDT查询的时间复杂度依赖于严格 \(\log n\) 的树高,这使得我们不能使用类似treap的期望 \(O(\log n)\) 或者类 \(O(\log n)\) 去做。
我们有两个方法维护。
1.定期重构
由于建树是 \(O(n\log n)\) 的,我们可以每 \(B\) 次插入重构一遍,查询复杂度 \(O(\sqrt n +B)\) ,插入复杂度 \(O(\frac{n\log n} B)\) 。
\(n,q\) 同阶时 \(B\) 取 \(\sqrt{n\log n}\) 最优,此时查询插入时间复杂度均为 \(O(\sqrt{n\log n})\) 。
2.二进制分组
KDT合并的时间复杂度为 \(O(n\log n)\) ,考虑维护 \(2\) 的整数次幂棵KDT,若出现两个相同大小的KDT就将其合并,插入的总时间复杂度为 \(O(n\log^2 n)\) 的,查询的时间复杂度\(O(∑_{𝑖≥0}\sqrt{\frac n{2^i}}) =O(\sqrt n)\) 。

浙公网安备 33010602011771号