(Splay)的复杂度分析
不论插入,删除还是访问,我们可以发现它们的复杂度都和(splay)操作的复杂度同阶,只是一点常数的区别
我们不妨假设有(n)个点的(splay),进行了(m)次(splay)操作
采用势能分析
我们记(w(x) = left lceil log_2 (size(x)) ight ceil),注意以(2)为底和上取整
我们定义势能函数为(varphi = sum w(x))
(记第(i)次操作操作完之后,势能为(varphi(i)))
只需要估计出(varphi(m) - varphi(m - 1) + varphi(m - 1) - varphi(m - 2) ... + varphi(1) - varphi(0) + varphi(0))的大小即可
(即初始势能和每次的势能变化量的和)
显然,(varphi(0) leqslant n log n)
(splay)操作的具体定义为:
如果父节点是根,那么旋转一次
如果父节点和爷节点所处子树方向一致,那么先旋转父亲再旋转自己
否则,旋转两次自己
实际上可以归结于(zig),(zag),(zig-zig),(zag-zag),(zig-zag),(zag-zig)操作
由于(zig)和(zag)是对称的操作
因此,只需要对(zig),(zig-zig),(zig-zag)操作分析复杂度即可
(zig)操作
势能的变化量为(1 + w'(x) + w'(fa) - w(x) - w(fa) leq 1 + w'(fa) - w(x) leq 1 + w'(x) - w(x))
(zig-zig)操作
势能变化量为(1 + w'(x) + w'(fa) + w'(g) - w(x) - w(fa) - w(g))(缩小了常数的影响,但不能无视)
(leq 1 + w'(fa) + w'(g) - w(x) - w(fa) leq 1 + w'(x) + w'(g) - 2w(x))
这是神仙复杂度证明中非常神奇的地方,通过一些有趣的性质,让常数项的代价合并到了势能的变化中
我们不妨设(a = w'(g), b = w(x)),那么注意到(w'(x) = a + b + 1)
由于$2w'(x) - w'(g) - w(x) = left lceil log_2 (a + b + 1) ight ceil - left lceil log_2 a ight ceil + left lceil log_2 a + b + 1 ight ceil - left lceil log_2 b ight ceil $
注意到(a, b)在上式中是对称的,不妨设(a geq b)
(geq left lceil log_2 (a + b + 1) ight ceil - left lceil log_2 b ight ceil geq left lceil log_2 (2b + 1) ight ceil - left lceil log_2 b ight ceil geq left lceil log_2 b ight ceil + 1 - left lceil log_2 b ight ceil geq 1)
因此有(1 leq 2w'(x) - w'(g) - w(x)),我们将(1 + w'(x) + w'(g) - 2w(x))中的(1)放缩,可以得到
(leq 3(w'(x) - w(x)))
(zig-zag)操作
势能变化量为(1 + w'(x) + w'(fa) + w'(g) - w(x) - w(fa) - w(g) leq 1 + w'(fa) + w'(g) - w(x) - w(fa) leq 1 + w'(g) + w'(fa) - 2w(x))
由上文的结论,我们知道这里可以把(1)放缩成(1 leq 2w'(x) - w'(g) - w'(fa))
因此(leq 2(w'(x) - w(x)))
把以上三种操作的势能全部放缩为(leq 3(w'(x) - w(x)))
不妨假设(splay)一次,依次访问了点(x_1, x_2 ... x_n),最后(x_1)会成为新的根
那么,最后的势能实际上是(3(w'(x_1) - w(x_1) + w''(x_1) - w'(x_1) + .... + w(n) - w^{'''.....}(x_1)) + 1 = 3 * (w(n) - w(x_1)) + 1leq log_2 n)
因此,(varphi(m) - varphi(m - 1) + varphi(m - 1) - varphi(m - 2) ... + varphi(1) - varphi(0) + varphi(0) = n log n + m log n)
即(n)个点的(splay),做(m)次(splay)操作,复杂度为(O(n log n + m log n))
(LCT)的复杂度分析
不咕了....
(LCT)的所有操作可以看做只有(access)操作,其他都是常数
那么(access)操作一共有两部分
-
在(splay)中走的复杂度
-
访问虚边的复杂度
首先是在(splay)中走的复杂度
定义(w(x) = left lceil log_2 (size(x)) ight ceil),(size(x))指(x)的所有虚边和实边的子树大小的和
我们定义势能函数为(varphi = sum w(x))
不妨设它依次访问了(x_1, x_2 ..., x_p)
那么,类似上文(splay)的复杂度分析,我们可以得到总的一次势能变化量为(-w(x_1) +w(x_2) - w(x_2) + w(x_3) ... +w(x_p) + 1leq w(x_p) + 1 = O(log n))
这也就是(splay)的(finger-search)的性质
初始势能为(n log n),因此这一部分的复杂度为(O(nlog n + m log n))
访问虚边的复杂度
我们定义势能函数(phi),为所有重虚边(儿子的子树大小大于等于自己的二分之一的虚边)的数量
那么,每次访问至多走(log)条轻虚边,也就至多带来(log)条重虚边,也就是以(O(log))的代价增加(log)的势能
而每次访问一条重虚边就需要付出(O(1))的代价来减小(1)的势能,并且访问完重虚边之后,不会有新的重虚边产生
因此,最终的复杂度是初始势能和势能变化量(实际操作的代价和势能变化量相同)的和,也就是(O(n + m log n))
因此,(LCT)的复杂度为(O(n log n + m log n))