Splay 复杂度分析

众所周知,Splay 的复杂度分析需要用一个叫做“势能分析法”的东西。

所以首先得解释一下这个势能分析是个什么来头。

势能分析法

简介

我们在某些时间复杂度是均摊的问题上,往往进行草率的感性理解,虽然理解了复杂度是从何而来,但严谨证明却比较麻烦。

我们可以考虑在单次操作复杂度不好分析,可能复杂很大的时候(例如 splay 操作),为数据结构引入势能概念,当时间松时存储势能,当时间紧时释放势能。

可以理解为“存款”和“取款”。在某次操作耗时较少时,将盈余的时间分摊给其他耗时较长的操作。

一些定义

设一个数据结构为 D0D_0,进行 mm 次操作,分别为 c1,c2,,cmc_1, c_2, \ldots, c_m。定义第 kk 次操作后的数据结构为 DkD_k。定义势函数 Φ(Dk)\Phi(D_k) 表示数据结构 DkD_k 的势能,这个函数将一个数据结构映射到一个实数上。

我们定义一次操作的摊还代价为 ci^=ci+Φ(Di)Φ(Di1)\hat{c_i} = c_i + \Phi(D_i) - \Phi(D_{i - 1}),即本次操作的实际代价加上操作前后数据结构势能的变化量。

这样,mm 次操作的总摊还代价为

i=1mci^=i=1mci+Φ(Dm)Φ(D0)\sum_{i = 1}^{m} \hat{c_i} = \sum_{i = 1}^{m} c_i + \Phi(D_m) - \Phi(D_0)

因此,

i=1mci=i=1mci^+Φ(D0)Φ(Dm)\sum_{i = 1}^{m} c_i = \sum_{i = 1}^{m}\hat{c_i} + \Phi(D_0) - \Phi(D_m)

这样,我们通过得出 i=1mci^\sum_{i = 1}^{m} \hat{c_i}Φ(D0)Φ(Dm)\Phi(D_0) - \Phi(D_m) 的上界,就可以求出 i=1mci\sum_{i = 1}^{m} c_i 的上界了!

Splay 的势能分析

首先通过观察可以发现,Splay 的所有操作的代价都可以理解为常数倍的 splay 操作。

因此我们只需考虑 splay 操作。

设一个 Splay 中共 nn 个点,每个点对应的子树大小为 s(i)s(i),每个点的势能 ϕ(i)=log2s(i)\phi(i) = \left\lceil\log_2 s(i)\right\rceil

整个 Splay 的总势能为 Φ(D)=i=1nϕ(i)\Phi(D) = \sum_{i = 1}^{n} \phi(i)

splay 操作有三种情况,下面分类讨论。

zig (zag)

xx 的父节点为根时,我们通过一次单旋将 xx 旋转到根。

ΔΦ=ϕ(x)+ϕ(y)ϕ(x)ϕ(y)\Delta\Phi = \phi(x') + \phi(y') - \phi(x) - \phi(y)

ϕ(x)=ϕ(y)\because \phi(x') = \phi(y)

ΔΦ=ϕ(y)ϕ(x)\therefore \Delta\Phi = \phi(y') - \phi(x)

ϕ(x)ϕ(y)\because \phi(x') \ge \phi(y')

ΔΦ=ϕ(y)ϕ(x)ϕ(x)ϕ(x)\therefore \Delta\Phi = \phi(y') - \phi(x) \le \phi(x') - \phi(x)

因为 zig 操作需要 rotate 一次,rotateO(1)O(1) 的,所以

c^zig=ΔΦ+1ϕ(x)ϕ(x)+1\hat{c}_{\mathrm{zig}} = \Delta\Phi + 1 \le \phi(x') - \phi(x) + 1

同理可证 zag 的摊还代价,因为 zig 和 zag 是对称的。

zig-zig (zag-zag)

xx 与父节点的儿子类型相同的时候,先旋转 xx 的父节点,再旋转 xx

ΔΦ=ϕ(x)+ϕ(y)+ϕ(z)ϕ(x)ϕ(y)ϕ(z)\Delta\Phi = \phi(x') + \phi(y') + \phi(z') - \phi(x) - \phi(y) - \phi(z)

ϕ(x)=ϕ(z)\because \phi(x') = \phi(z)

ΔΦ=ϕ(y)+ϕ(z)ϕ(x)ϕ(y)\therefore \Delta\Phi = \phi(y') + \phi(z') - \phi(x) - \phi(y)

ϕ(x)ϕ(y),ϕ(x)ϕ(y)\because \phi(x') \ge \phi(y'), \phi(x) \le \phi(y)

ΔΦϕ(x)+ϕ(z)2ϕ(x)\therefore \Delta\Phi \le \phi(x') + \phi(z') - 2\phi(x)

我们知道,当 x,y>0,x+y1x, y > 0, x + y \le 1 时,

(xy)20x22xy+y20x2+2xy+y24xy(x+y)24xyxy(x+y)24log2x+log2y=log2xylog2(x+y)24\begin{aligned} \because (x - y)^2 & \ge 0\\ \therefore x^2 - 2xy + y^2 & \ge 0\\ \therefore x^2 + 2xy + y^2 & \ge 4xy\\ \therefore (x + y)^2 & \ge 4xy \\ \therefore xy & \le \frac{(x + y)^2}{4}\\ \log_2 x + \log_2 y & = \log_2 xy \\ & \le \log_2 \frac{(x + y)^2}{4} \\ \end{aligned}

取等当且仅当 x=yx = y

x+yx + y 取最大值 11 时,log2(x+y)24\log_2\frac{(x + y)^2}{4} 取最大值 2-2

因此

log2x+log2y2\log_2 x + \log_2 y \le -2

那么,

ϕ(x)+ϕ(z)2ϕ(x)=(ϕ(x)ϕ(x))+(ϕ(z)ϕ(x))=(log2s(x)log2s(x))+(log2s(z)log2s(x))=log2s(x)s(x)+log2s(z)s(x)\begin{aligned} \phi(x) + \phi(z') - 2\phi(x') & = (\phi(x) - \phi(x')) + (\phi(z') - \phi(x')) \\ & = (\log_2 s(x) - \log_2 s(x')) + (\log_2 s(z') - \log_2 s(x')) \\ & = \log_2 \frac{s(x)}{s(x')} + \log_2 \frac{s(z')}{s(x')} \\ \end{aligned}

s(x)+s(z)s(x)\because s(x) + s(z') \le s(x') \\

s(x)s(x)+s(z)s(x)1\therefore \frac{s(x)}{s(x')} + \frac{s(z')}{s(x')} \le 1 \\

s(x)s(x)>0,s(z)s(x)>0\because \frac{s(x)}{s(x')} > 0 , \frac{s(z')}{s(x')} > 0

log2s(x)s(x)+log2s(z)s(x)2\therefore \log_2 \frac{s(x)}{s(x')} + \log_2 \frac{s(z')}{s(x')} \le -2

ϕ(x)+ϕ(z)2ϕ(x)2\therefore \phi(x) + \phi(z') - 2\phi(x') \le -2

ΔΦϕ(x)+ϕ(z)2ϕ(x)=(3ϕ(x)3ϕ(x))+(ϕ(x)+ϕ(z)2ϕ(x))3ϕ(x)3ϕ(x)2\begin{aligned} \therefore \Delta\Phi & \le \phi(x') + \phi(z') - 2\phi(x) \\ & = (3\phi(x') - 3\phi(x)) + (\phi(x) + \phi(z') - 2\phi(x)) \\ & \le 3\phi(x') - 3\phi(x) - 2 \end{aligned}

因为 zig-zig 操作需要 rotate 两次,所以

c^zigzig=ΔΦ+23ϕ(x)3ϕ(x)\hat{c}_{\mathrm{zigzig}} = \Delta\Phi + 2 \le 3\phi(x') - 3\phi(x)

同理可证 zag-zag 的摊还代价,因为 zag-zag 和 zig-zig 是对称的。

zig-zag (zag-zig)

xx 与父节点的儿子类型不同时,旋转两次 xx 节点。

ΔΦ=ϕ(x)+ϕ(y)+ϕ(z)ϕ(x)ϕ(y)ϕ(z)\Delta\Phi = \phi(x') + \phi(y') + \phi(z') - \phi(x) - \phi(y) - \phi(z)

ϕ(x)=ϕ(z)\because \phi(x') = \phi(z)

ΔΦ=ϕ(y)+ϕ(z)ϕ(x)ϕ(y)\therefore \Delta\Phi = \phi(y') + \phi(z') - \phi(x) - \phi(y)

ϕ(x)ϕ(y)\because \phi(x) \le \phi(y)

ΔΦϕ(y)+ϕ(z)2ϕ(x)=(2ϕ(x)2ϕ(x))+(ϕ(y)+ϕ(z)2ϕ(x))\begin{aligned} \therefore \Delta\Phi & \le \phi(y') + \phi(z') - 2\phi(x) \\ & = (2\phi(x') - 2\phi(x)) + (\phi(y') + \phi(z') - 2\phi(x')) \\ \end{aligned}

s(y)s(x)>0,s(z)s(x)>0,s(y)+s(z)s(x)\because \frac{s(y')}{s(x')} > 0, \frac{s(z')}{s(x')} > 0, s(y') + s(z') \le s(x')

ϕ(y)+ϕ(z)2ϕ(x)2\therefore \phi(y') + \phi(z') - 2\phi(x') \le -2

ΔΦ2ϕ(x)2ϕ(x)2\therefore \Delta\Phi \le 2\phi(x') - 2\phi(x) - 2

因为 zig-zag 操作需要 rotate 两次,所以

c^zigzag=ΔΦ+22ϕ(x)2ϕ(x)\hat{c}_{\mathrm{zigzag}} = \Delta\Phi + 2 \le 2\phi(x') - 2\phi(x)

可以再放缩一下,便于下一步计算。

ϕ(x)ϕ(x)0\because \phi(x') - \phi(x) \ge 0

c^zigzag3ϕ(x)3ϕ(x)\therefore \hat{c}_{\mathrm{zigzag}} \le 3\phi(x') - 3\phi(x)

同理可证 zag-zig 操作的摊还代价,因为 zag-zig 和 zig-zag 是对称的。

一次 splay 操作

回顾一下,我们有:

c^zigϕ(x)ϕ(x)+13(ϕ(x)ϕ(x))+1c^zigzig3(ϕ(x)ϕ(x))c^zigzag3(ϕ(x)ϕ(x))\hat{c}_{\mathrm{zig}} \le \phi(x') - \phi(x) + 1 \le 3(\phi(x') - \phi(x)) + 1 \\ \hat{c}_{\mathrm{zigzig}} \le 3(\phi(x') - \phi(x)) \\ \hat{c}_{\mathrm{zigzag}} \le 3(\phi(x') - \phi(x))

因此,我们将 xx 这个点旋转到根的时候,一路抵消,最后

ci^3(ϕ(root)ϕ(x))+1=3log2ns(x)+13log2n+1=O(logn)\begin{aligned} \hat{c_i} & \le 3(\phi(\mathrm{root}) - \phi(x)) + 1 \\ & = 3\log_2 \frac{n}{s(x)} + 1 \\ & \le 3\log_2 n + 1 \\ & = O(\log n) \end{aligned}

所有操作

i=1mci^=O(mlogn)\sum_{i = 1}^{m}\hat{c_i} = O(m\log n)

又因为

0Φ(D)nlog2n0 \le \Phi(D) \le n\log_2 n

所以

Φ(D0)Φ(Dn)=O(nlogn)\Phi(D_0) - \Phi(D_n) = O(n\log n)

因此

i=1nci=i=1nci^+Φ(D0)Φ(Dn)=O(mlogn)+O(nlogn)=O((n+m)logn)\begin{aligned} \sum_{i = 1}^{n} c_i & = \sum_{i = 1}^{n}\hat{c_i} + \Phi(D_0) - \Phi(D_n) \\ & = O(m\log n) + O(n\log n) \\ & = O((n + m)\log n) \end{aligned}

证毕。