某人奶了一口省选会考,于是认真学了学。
形态
k-D Tree 是一棵二叉搜索树,每个结点都对应 $k$ 维空间中的一个点,每个子树中的点都在且都仅在一个 $k$ 维超长方体内。
构建
假设已知 $k$ 维空间中的 $n$ 个互不相同的点的坐标,要将其构建为一棵 k-D Tree。
- 当前超长方体中只有一个点时直接返回该点。
- 选择一个维度与该维度上的一个切割点,将当前超长方体按这个维度及这个切割点分为两个超长方体。
- 将选择的切割点作为该子树的根,递归处理分出的两个超长方体。
容易发现,对于步骤 2,每次切割点选为该维度上的中位数,树高可以在 $O(\log n)$。
如何寻找中位数?可以使用类似快速排序的方法,并且每次只递归包含中位数的一侧,对于 $n$ 个元素的序列期望时间复杂度即为 $O(n)$。(可用algorithm
库中的nth_element()
实现)
每次选什么维度来割?理论上应当每次选方差最大的维度割常数应当最小,然而算法竞赛中较常用且方便的写法是直接轮流按每一维割。
插入与删除
点集可变,可以利用替罪羊树不平衡重构的方法把树高稳定在 $O(\log n)$。
然而实验证明定期整树重构通常来说常数更小。
查询超长方体
若该结点完全被包含于超长方体内,或完全与其无交可直接返回。
否则应递归两边。
可以证明复杂度最坏为 $O(n^{1-\frac{1}{k}})$。
习题
初值全为 0 的 $n\times n$ 二维矩阵上, $q$ 个操作:
- 单点修改。
- 矩形查询和。
强制在线,内存限制20M
,答案及过程量均int
范围内。$n\le 5\times 10^5, q\le 2\times 10^5$。
空间卡树套树,强制在线卡 CDQ 分治,于是只能 KDT。
不要不平衡重构,定期重构常数更小。
1 |
|