Euler Tour Tree 学习
本文不知道有没有错,因为作者没写过代码太离谱了。。当然现在有 Top Tree 这个也不是特别有用了,在 Werneck 的论文中提到, ETT 是最简单的动态树结构,也没有对 ETT 的操作进行详细的讲解,因为这些操作实在是太过于简单了。。
基本操作
一般来说我们大概实现下面几种操作
-
-
-
-
\operatorname{setvalue}(x,v)$ 设定节点 $x$ 对应的值为 $v -
-
-
一些概念
首先,对于一棵自由树
我们将其 Euler Tour 写出来是
[A]-AB-[B]-BA-[A]-AC-[C]-CE-[E]-EC-[C]-CF-[F]-FC-[C]-CA-[A]-AD-[D]-DE-[E]-ED-[D]-DA
这正是
每条边经过两次,而对于每个节点
此时 Tarjan 提出我们对于一个节点的访问只保留一次,而且我们并不在意保留哪一次,然后 Euler Tour 就变成了一个循环双链表的表示。
[A]-AB-[B]-BA-AC-[C]-CE-[E]-EC-CF-[F]-FC-CA-AD-[D]-DG-[G]-GD-DA
然后我们将头尾也连起来即可。 Werneck 提出在任意点断开这个循环双链表,并存储在二叉搜索树中,使得该二叉搜索树的中序遍历为这个序列即可(既然是循环链表,当然不用在乎从哪里断开)。
我们在这里加入更强的限制,即让中序遍历第一个为该树的根,换句话说,我们只维护有根树,但是支持
接下来我们观察上述基本操作对于该序列的影响。
\operatorname{findroot}(x)
寻找序列的第一个元素,对应到二叉搜索树中即 left most 的节点。
\operatorname{evert}(x)
为了支持
\operatorname{cut}(x)
为了支持这个操作,我们需要能够比较快速的查询
[parent(x)]-...-(parent(x),x)-...-(x,parent(x))-...
我们使边
我们一定要保证
\operatorname{cut}(x,y)
与上面类似的做法即可,如果保证边
\operatorname{link}(x,y)
我们只需验证
\operatorname{findmin}(x)
通过 LCT 找到
子树加/子树和
因为没有链的询问,所以我们只需额外记录一个 size[x] 表示以 size[x] = size[left_child(x)] + size[right_child(x)] + int(is_vertex(x)); 这样应用类似于线段树 lazy propagation 即可。