算法学习之:动态树(link-cut-tree,下文简称lct)
前言:
经过大神对lct的各种狂吹之后,作为蒟蒻一只的我就来学习lct了,%了几份博客之后,大概明白了lct是怎么做。发现其实lct好像并没有想想中的那么难。当然lct的最低门槛是splay,其次当然就是树链剖分。当然理论上来说树链剖分不看的话lct其实可学,但是可能光是理解就要好久。所以想学lct的小伙伴们还是先去学学splay和树剖咯。
从一道简单题说起:
题目链接:戳这里
题目大意:
森林上各种操作,包括森林树上的路径询问,拆分,合并和单点修改。显然,如果说把拆分以及合并去掉的话,这道就是一道非常裸的树剖题。但是,树剖成立的前提条件就是树的形态是不变的,而显然,在森林中树的拆分与合并使得树的结构是不定的,因此我们希望有某种数据结构,支持树链的拆分合并,并且复杂度是nlog级别的,这就是动态树。
算法详解:
几个定义:
Access:如果这个点刚刚被访问过,那么称这个节点刚刚被执行了Access操作。
PreferredChild:在节点u的子树中,如果最后一个被访问的节点v在当前结点u的w子树中,那么称w为u的Preferred Child,如果节点u本身就是最后一个被访问的节点,那么u没有Preferred Child。
延伸定义:Preferred Edge和Preferred Path,分别表示Preferred Child的父边以及以其形成的路径。
接下来闭上眼睛,把这个几个概念回顾一下,直到你能把他的定义背出来。并且类比一下之前其他的算法概念。然后你会发现:超级像树剖的做法,只不过这棵树的Preferred Child不一定是子树节点个数最多的,因为这棵树的结构会随时变化,下文会提到。
数据结构登场——平衡树
由上面的操作,我们得到了若干条Preferred Path,对于每条Preferred Path,我们以深度为关键字①,维护一棵平衡树(当然是选择Splay,因为要支持转来转去的操作),顺带说一句,这个平衡树有个好听的名字,叫做Auxiliary Tree(辅助树),然而这个概念并不