关于势能分析

可能有不少不严谨之处,太菜了请谅解。

之前对于 \(\text{splay}\) 的复杂度一直不是很懂,今天进行了一个势能分析的学习。

势能分析,就是借助势能函数,将中间过程用势能函数来刻画以得到发杂度的一个上界,这样分析出来的一般是均摊复杂度。

例如,第 \(i\) 此操作的代价是 \(c_i\),那么设第 \(i\) 次操作的复杂度 \(C_i\) 是:

\[C_i = c_i + \phi(i) - \phi(i-1) \]

\[\sum {C_i} = \sum {c_i} + \phi(n) - \phi(0) \]

\(\sum{c_i}\) 和 $ \phi(n) - \phi(0) $ 存在一个上界,那么我们就算出了一个复杂度的上界。

一些例子:

1. 栈

维护一个栈,支持 \(\mathrm{push}\)\(\mathrm{pop}\)\(\mathrm{multipop}\) 三种操作,\(\mathrm{push}\) 和单次 \(\mathrm{pop}\) 的复杂度都是 \(O(1)\),进行 \(n\) 次操作,分析其复杂度。

直觉来看,复杂度是 \(O(n)\) 的,怎么证明呢?现定义势能函数 \(\phi(i)\) 为第 \(i\) 次操作后栈内元素个数。那么:

  • \(\mathrm{push}\)\(C_i = c_i + \phi(i) - \phi(i-1) = 1 + 1 =2\)
  • \(\mathrm{pop}\)\(C_i = c_i + \phi(i) - \phi(i-1) = 1 - 1 =0\)
  • \(\mathrm{multipop(k)}\)\(C_i = c_i + \phi(i) - \phi(i-1) = k - k =0\)

\(n\) 次操作,因此复杂度 \(O(n)\)

2. 二进制加法

一个二进制数,从 \(1\) 加到 \(n\)。证明时间复杂度。

定义 \(\phi(i)\) 为第 \(i\) 次操作后 \(1\) 的个数。

一次加 \(1\) 相当于 \(k\)\(1 \rightarrow 0\) 和一次 \(0 \rightarrow 1\),则:

\[C_i = c_i + \phi(i) - \phi(i-1) = k + 1 + \phi(i-1) - k + 1 - \phi(i-1) = 2 \]

一次操作均摊 \(O(1)\),总的就是 \(O(\log n)\)

2.5 一些理解

  • 势能分析的作用,就在于通过设计函数,把时间长的操作拼到时间短的上面。
  • 由上一条的启发,我们得到一个设计函数的思路:执行时间长的操作时,势能一般是降低的,时间短的操作时反之。
  • \(C_i = c_i + \phi(i) - \phi(i-1)\),中间的代价和势能之间的相加有什么意义吗?其实这没有任何实际意义,只是我们利用其来进行一个平衡。

3. Splay

现在要设计一个势能函数,根据我们的直觉,势能函数理应与 \(\mathtt{Splay}\) 的平衡有关。

下面记 \(\left|x\right|\)\(x\) 子树的大小。

若一 \(n\) 个点的 \(\mathtt{Splay}\) 进行了 \(m\)\(\mathtt{Splay}\) 操作。
\(\phi(i) = \log(size(i))\),整棵 \(\mathtt{Splay}\) 的势能函数 \(\Phi(T) = \sum{\phi(x)}\)

则一次旋转的代价为 \(C_i = O(1) + \Delta\Phi(T)\)

设要旋转的节点为 \(x\),其父亲和父亲的父亲分别为 \(y\)\(z\),那么:

  • 进行一次 \(\text{zig}\) 操作时:

\[\begin{align*} C_i & = 1 - \phi(x) - \phi(y) + \phi'(x) + \phi'(y)\\ & = 1 + \phi'(y) - \phi(x)\\ & \le 1 + \phi'(x) - \phi(x)\\ \end{align*} \]

  • 进行 \(\text{zig-zag}\) 操作时:

\[\begin{align*} C_i & = 1 - \phi(x) - \phi(y) -\phi(z) + \phi'(x) + \phi'(y) +\phi'(z)\\ & = 1 + \phi'(y) + \phi'(z) - \phi(x) -\phi(y) \end{align*} \]

然后进行一个神秘的放缩:

因为旋转后

\[\left|x'\right| > \left|y'\right| + \left|z'\right| \]

因此

\[\phi'(z) + \phi'(y) - 2\phi'(x) < -1 \]

所以

\[\begin{align*} C_i & = 1 + \phi'(y) + \phi'(z) - \phi(x) -\phi(y)\\ & \le \phi'(y) + \phi'(z) - \phi(x) -\phi(y) - (\phi'(z) + \phi'(y) - 2\phi'(x))\\ & = 2\phi'(x) - \phi(x) - \phi(y)\\ & \le 2(\phi'(x) - \phi(x)) \end{align*} \]

  • 进行 \(\text{zig-zig}\) 操作时:

\[\begin{align*} C_i & = 1 - \phi(x) - \phi(y) -\phi(z) + \phi'(x) + \phi'(y) +\phi'(z)\\ & = 1 + \phi'(y) + \phi'(z) - \phi(x) -\phi(y) \end{align*} \]

又因为

\[\begin{equation} \left|x'\right| = \left|x\right| + \left|z'\right| + 1 \end{equation}\]

因此

\[\phi(x) + \phi(z') - 2\phi'(x) = \log \frac{|x||z'|}{|x'|} < \log \frac{|x'|}{4|x'|} = -2 < -1 \]

代换得:

\[\begin{align*} C_i & = 1 + \phi'(y) + \phi'(z) - \phi(x) -\phi(y) \\ & = \phi'(y) + \phi'(z) - \phi(x) -\phi(y) - (\phi(x) + \phi(z') - 2\phi'(x)) \\ & \le \phi'(x) + \phi'(z) - \phi(x) -\phi(x) - (\phi(x) + \phi(z') - 2\phi'(x)) \\ & = 3(\phi'(x) -\phi(x)) \end{align*} \]

  • 如果 \(\text{zig-zig}\) 操作两次都转的是 \(x\) 的话,\((1)\) 式就不在成立,我们也很难通过放缩把那个 \(O(1)\) 消掉,那复杂度就不对了。

综上,除了最后一次旋转外,其余的常数都被我们消掉了。因此一次 \(Splay\) 复杂度为 \(O(1) + 3(\phi(root) - \phi(x_0)) < 3\log n\)

\(m\) 次操作,总复杂度为 \(m\log n + \Delta \Phi(T) = (m+n)\log n\)

4. LCT

\(\mathtt{LCT}\) 的复杂度只来源于 \(\text{Access}\) 操作,因为单独的 \(\text{Splay}\) 操作是严格小于 \(\text{Access}\) 中的多次 \(\text{Splay}\) 的。(应该是的吧?)

沿用对 \(\text{Splay}\) 的势能分析,对于 \(\text{Access}\) 中的第 \(i\)\(\text{Splay}\)

\[C_i = O(1) + 3(\phi(root_i) - \phi(x_i)) \]

因为 \(\phi(root_i)\) 一定小于 \(\phi(x_{i+1})\),因此:

\[\sum{C_i} < k + \phi(root) - \phi(x_0) < k + \log n \]

其中 \(k\) 是换链次数,现在只需要证明 \(k\) 的复杂度就好了。证明过程非常神奇:

对原树重链剖分,现在边有了轻重之分。

记势能函数 \(\Phi(T)\) 为整棵树中重虚边的数量。那么在一次 \(\text{Access}\) 操作中:

  1. 重实边切成轻实边,\(\Phi(T)\) 增加 \(1\)
  2. 轻实边切成重实边,\(\Phi(T)\) 减少 \(1\)

注意到一个点到根的路径中最多经过 \(\log n\) 条轻边,因此 \(\Phi(T)\) 最多增加 \(n \log n\) 次,相应地切边最多也只有 \(n\log n\) 级别。

这样我们就用势能分析证明了 \(\mathtt{LCT}\) 的复杂度。

(其实我们也顺带证明了假如说用 \(\mathtt{fhq\; Treap}\) 来维护的话复杂度为什么是 \(n \log^2 n\) 的,因为一棵 \(\mathtt{fhq\; Treap}\) 只保证了深度为 \(\log n\),并不能像 \(\mathtt{Splay}\) 一样看成一个整体来看待。

参考资料

Splay 树 - OI Wiki
势能分析 - Achtoria - 博客园

posted @ 2024-08-13 13:52  KIreteria  阅读(111)  评论(0)    收藏  举报