基于替罪羊树维护的 K‑D Tree 复杂度证明
摘要
本文证明了替罪羊树维护 K‑D Tree 的查询、重构复杂度,打破算法竞赛社区关于该做法复杂度的错误观点。
This article proves the query and reconstruction complexity of the scapegoat tree maintaining a K‑D Tree, refuting the incorrect belief in the competitive programming community regarding the complexity of this approach.
前言
很多选手会使用替罪羊树结构来维护.但是注意到在刚才的复杂度分析中,要求儿子的子树大小严格减半,即树高必须为严格的 \(\log n+O(1)\),而替罪羊树只满足树高 \(O(\log n)\),故查询复杂度无法保证.
——OI wiki K‑D Tree
我写完后估计就要改了。
本文的目的即证明使用替罪羊树维护 K‑D Tree 的复杂度。其中,本文重点分析二维情况。
如果你并不了解这一做法,可以参考 aaron0919 的 P14312 【模板】K-D Tree の题解,但是其中的复杂度证明是错误的,详细原因请参考后文。
本文仅讨论交错建树。对于二维而言,即建树时每层的排序方式即按 \(x\) 坐标排序与按 \(y\) 坐标排序交替。
前置知识
我们会使用的工具:
- 均摊分析和替罪羊树的复杂度证明
- Akra‑Bazzi 定理,可以参考 GONGGONGJOHN 的从主方法到Akra-Bazzi定理
Akra‑Bazzi 定理
现不加证明地给出 Akra‑Bazzi 定理:
设 \(f(x)\) 为非负函数,
满足
对于定义在非负实数的函数 \(f(n)\),称 \(f(x)\) 满足多项式增长条件当且仅当 \(\exists c_1,c_2>0,\{b_k\},b_i \in(0,1),\forall x \ge 1,1 \le i \le k,u \in [b_i x,x],c_1 f(x) \le f(u) \le c_2 f(x)\)。
由定义可知,若存在 \(c \ge 0\),使得 \(|g^\prime(x)| \in \mathcal{O}(n^c)\),则 \(g(x)\) 满足多项式增长条件。
特别地,\(a,b\in \mathbb R,f(n)= \mathcal{O}(n^a\log ^b n)\),则 \(f(n)\) 满足多项式增长条件。
则
其中 \(p\) 为方程 \(\sum \limits _{i=1}^k a_i b_i ^p =1\) 的实数根。
为什么和论文 [1] 中的描述不一样
我本来是想要用论文 [1] 中的版本,但是我看到里面有这样一句话:
\(g(x)\) is defined for real values \(x\), and is bounded, positive and nondecreasing function \(\forall x \ge 0\)
此处的 \(g(x)\) 即上文的 \(f(x)\)。
注意到其中有一个 bounded,非常奇怪,因为连 \(g(n)=n\) 都不满足,这不合理。于是检索发现参考资料 [5] 的问答,接着查阅了参考资料 [4] 中 Leighton 的讲义,认为 bounded 是个 typo。
由于参考资料 [4] 中的描述 "These conditions are somewhat less restrictive than those of [1]",且为互联网上最常见的描述,所以选择了这种描述。
关于平衡树相关的一些术语
- \(\alpha\)‑重量平衡:在所有结点处,左右儿子子树大小均不超过该节点的子树大小的 \(\alpha\) 倍;
- \(\alpha\)‑高度平衡:树的高度不超过 \({\log _{\alpha^{-1}} (|T|) }\),其中 \(T\) 为树的大小。
\(\alpha\)‑重量平衡可以推出 \(\alpha\)‑高度平衡。因为从根走到最深的叶子,深度每增加一子树大小至多为其父亲的 \(\alpha\) 倍。
但是 \(\alpha\)‑高度平衡不能推出 \(\alpha\)‑重量平衡。举一个反例左子树为深度为 \(k\) 的链,大小为 \(k\);右子树为深度为 \(k\) 的完全二叉树大小为 \(2^k-1\),整棵树总结点树为 \(2^k+k\)。当 \(k\) 足够大时,对于任意 \(\alpha>0.5\),这颗树可以满足 \(\alpha\)‑高度平衡;但左右子树差异极大,无法满足 \(\alpha\)‑高度平衡。
完全平衡时的查询复杂度证明
借鉴了 OI wiki K‑D Tree 的证明。
先考虑二维情况。
若查询的矩形为 \(R\),让我们考虑一个结点代表的矩形 \(P\) 有以下三种情况:
- \(R\) 完全包含 \(P\);
- \(R\) 和 \(P\) 相离;
- \(P\) 完全包含 \(R\);
- \(P\) 与 \(R\) 相交但互不包含。
其中 3 和 4 两种情况是要继续递归的,即复杂度为 3 和 4 两种情况的结点数之和。
而第 3 种情况有一个平凡的上限:\(\mathcal{O}(h)=\mathcal{O}(\log n)\),\(h\) 为树高。
重点来考虑第 4 种情况。由于位于第 4 种情况时,一定在矩形的边缘。我们需要统计的总点数一定小于四个条边上的矩形个数和。
每个结点会的四个孙子结点将该矩形分为四个子矩形。而一条线段只能通过这其中的两个子矩形,所以可以得到这部分的递归式:
由主定理解得
这个大于 \(\mathcal O(\log n)\)
类似地分析可以得到 \(k\) 维的情况:
由主定理,得到经典结论:
替罪羊树维护的查询复杂度证明(二维情况)
有了上面的基础,我们可以考虑在替罪羊树上有什么不同。
可以发现,唯一的区别就是划分出来的四个子矩形大小不相同。
考虑一种极端情况:所有子树都恰好满足 \(\alpha\)‑重量平衡。为了方便我们假设现在讨论的子树大小为 \(n\)。那么四个孙子结点的子树的大小分别为:
取其中最大的两个,得到递归式:
可以直接套用 Akra‑Bazzi 定理。
我们先讨论一个特殊情况:\(\alpha=0.6=\frac{3}{5}\)。
则
这是一个超越方程,没有初等函数通式解。通过二分等方法可以解得
而
故总复杂度为
而在 OI 可能的数据范围内(\(n \le 10^6\)),\(n^{0.07} \le 2.63\),这个复杂度和 \(\Theta(\sqrt n)\) 几乎没有区别。
更一般地,考虑函数
考察参数 \(\alpha\) 的取值对零点的影响。
由于 \(\alpha \in (0.5,1)\),\(g(x)\) 在 \(\mathbb R_{+}\) 单调递减。故函数有唯一零点。
我们猜想 \(g(0.5) >0\),这等价于
左右显然都是正的。两边平方,得
同时除以正数 \(1-\alpha\),得
显然成立。故当 \(\alpha \in (0,5,1)\) 时,\(g(0.5)>0\)。
而 \(g(1)=\alpha^2+\alpha(1-\alpha)-1=\alpha-1<0\)。
故 \(p \in(0.5,1)\)。
则
故复杂度为
当 \(\alpha \in(0.5,0.75]\) 时,\(p \in (0.5,0.68]\)。而 \((10^5)^{0.18} \le 8\),在 OI 中可以视为常数。
通过观察 \(\alpha-p\) 图像,我发现这个超越函数在 \((0.5,0.9)\) 几乎为线性,线性回归得到 \(p(\alpha)\approx 0.7002\alpha +0.1511\),在 \((0.5,0.9)\) 的误差在小数点后三位,几乎可以忽略。这样,计算复杂度时就没有必要解超越方程了。
所以,替罪羊树维护的 K‑D Tree 复杂度是有保障的,只是比根号略微高一点。这就是为什么大家认为其复杂度错误但多年来没有人成功地 Hack 的原因。
一个伪证的批驳
在上述介绍替罪羊树维护 K‑D Tree 的文章 aaron0919 的 P14312 【模板】K-D Tree の题解中,其证明最重要的是这个式子:
现不考虑其没带 \(\Theta\) 或 \(\mathcal{O}\) 的不严谨。其核心错误在于第二个约等号:
由于替罪羊树是只能保证 \(\alpha\)‑高度平衡,树高可以达到
则代入得
比如代入 \(\alpha=0.6\),得到复杂度约为 \(\Theta(n^{0.68})\);代入 \(\alpha=0.75\),得到复杂度约为 \(\Theta(n^{1.20})\):这个结果明显劣于上面的分析,更不是其所称的根号。而且即使修正后 \(\alpha\) 稍大时复杂度就超过平凡的上界 \(\mathcal{O}(n)\),没有很大的实际价值。
替罪羊树的重构复杂度证明
替罪羊树满足
否则会进行重构。
重构完成的瞬间,子树满足 \(\frac{1}{2}\)‑重量平衡,左右子树大小相差最多为 \(1\)。
我们现在考虑:从一个刚刚重构好了的满足 \(\frac{1}{2}\)‑重量平衡的子树,至少要插入 \(d\) 给点才会使得这个这个子树不满足 \(\alpha\)‑重量平衡。
设当前子树大小为 \(n\),其中左子树大小就为 \(\lceil{\frac{n-1}{2}}\rceil\),右子树大小为 \(\lfloor\frac{n-1}{2}\rfloor\)。最极端的情况是所有的都插入到同一个左子树中。那么当该子树不满足 \(\alpha\)‑重量平衡时,满足:
将 \(\left\lceil{\frac{n-1}{2}}\right\rceil\) 放缩为 \(\frac{n}{2}\)。
这是一个下界。记 \(c=\frac{\alpha-0.5}{1-\alpha}\)。
而重建一个大小为 \(n\) 的子树所用时间为 \(\Theta(n\log n)\)。(按 nth_element 的平均复杂度为线性计算,如果追求严格可以使用 median of medians 算法,但常数较大)
得到重构的代价为 \(\frac{\Theta(n \log n)}{s} \lt \frac{\Theta(n \log N)}{cn}=\mathcal{O}(\frac{(1-\alpha)\log N}{\alpha-0.5})\),其中 \(N\) 为整棵树最多的结点树,显然 \(N \ge n\)。
这样,单次重构时路径上每个点的均摊代价为 \(\mathcal{O}(\frac{(1-\alpha) \log N}{\alpha-0.5})\)。
而插入时还经过 \(\log _{\alpha ^{-1}} N\) 个点,故总共的代价为 \(\mathcal{O}(\frac{1-\alpha}{\alpha-0.5}\log N \log_{\alpha^{-1}} N)\)。证毕。
由于插入找到一个数位置的复杂的为 \(\mathcal{O}(\log _{\alpha ^{-1}} {N})\),相对于重构可以忽略。
\(\alpha\) 的最优取值
我们求出了修改、查询的复杂度,这可以指导我们求 \(\alpha\) 的理论最优值。
假设插入、查询比例为 \(1:1\),则我们可以得到一个函数:
在固定 \(n=10^5\) 时,\(\alpha \approx 0.63\) 时最优。
实践中可以根据表现和常数调参,建议以 \(\alpha = 0.6= \frac{3}{5}\) 开始。
高维情况
从一个上述四类点向下深度为 \(k\) 会划分成从一个 \(k\) 维超立方体划分成 \(2^k\) 个子 \(k\) 维超立方体,大小依次为 \((\alpha+(1-\alpha))^k\) 二项式展开的结果。
若 \(k\) 为奇数,最大的 \(2^{k-1}\) 个为 \(\binom{k}{0}\) 个 \(\alpha ^k\),\(\binom{k}{1}\) 个 \(\alpha ^{k-1} (1-\alpha)\),一直到 \(\binom{k}{\frac{k-1}{2}}\) 个 \(\alpha ^{\frac{k+1}{2}}(1- \alpha)^{\frac{k-1}{2}}\)。
复杂度为
Akra‑Bazzi 方程为:
这个超越方程没有初等通式解,也不好分析。考虑三维情况:
这也没有初等通式解。代入 \(\alpha=0.6\),解得 \(p \approx 0.76\);代入 \(\alpha=0.7\),解得 \(p \approx 0.85\):这时复杂度已经很高了,建议根据实际表现适当调小 \(\alpha\)。
当 \(k\) 为偶数时,可得递归式
而 \(k\) 为任意值时实在难以分析,且 \(k\) 较大时和暴力差距不大,故略去。
一些留给读者的开放问题
- \(\Theta(n^p)\) 这个上界是紧的吗?
- 建树时可能还有另一种方法——方差划分——这种方法使用替罪羊树维护是否能证明其复杂度有保障?
- 本文表明不完全平衡的 K‑D Tree 复杂度仍然可能有保证,那么能否换用其他的平衡树维护?
参考资料
- Akra M , Bazzi L .On the Solution of Linear Recurrence Equations[M].Kluwer Academic Publishers,1998.
- Galperin I , Rivest R L .Scapegoat Trees[J].DBLP, 1993.DOI:10.1145/313559.313676.
- OI Wiki 上的 K‑D Tree 和替罪羊树的复杂度证明
- Leighton T. Notes on better master theorems for divide-and-conquer recurrences. MIT Lecture Notes, 1996. 这是一份 MIT 的讲义。可以在 MIT 官方课程网站获得。
- 一个关于 Akra‑Bazzi 定理适用条件的问答:asymptotics - Why does Akra-Bazzi need that toll-function g is bounded? - Computer Science Stack Exchange
- aaron0919 的 P14312 【模板】K-D Tree の题解
- GONGGONGJOHN 的 从主方法到Akra-Bazzi定理
本文可能火药味比较足,敬请谅解。如有错误,欢迎批评指正。

浙公网安备 33010602011771号