【专题小结】数据结构

来源:互联网 发布:vscode php注释插件 编辑:程序博客网 时间:2024/04/30 11:53

哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈

可持久化线段树

动态树相关

动态树东西很多,说白了也就LCT,ETT,Top-tree.
今天只学了这三种的思想,具体实现还得好好打。

LCT的大致思想是,动态维护树链剖分。
树链剖分中,我们有重边和轻边,重链上DFS序是连续的一段,任意一个点到根的路径上会经过不超过logn条轻边。可以通过线段树等数据结构维护重链的信息,由于只有logn条轻边,我们一共只需要logn次查询,每次查询复杂度也为logn,总复杂度logn*logn。
那么动态的呢?
LCT的核心操作 access(x) 表示把x到根的路径设置为重链,每条重链的信息用splay来维护,每个spaly存这个重链的序列,中序遍历即为从浅到深。合并的时候把儿子的splay从右边插入父亲的splay,维护好这个中序=深度的性质。同样的,x在到根的路径上,均摊经过的轻边数量也是logn级别的。在路径上可能涉及轻重边的变换,如本来是重边的现在变成轻边,只需要把这个重链的splay给split成两个部分就好;本来是轻边的现在连接上了某一个重链,把这条轻边连接的两个splay合并就好。此处为意识流,自己看得懂就行,实在不行找论文研究把。注意access操作要把这个点的其他边全部变成轻边。

旋根(换根) 先access(x),然后把这个splay
整个翻转一下【原来深的(x)变成了深度最浅的】由于这个splay最浅的深度就是根,换根就完成了。
Link(x,y) access(x), Fa[x]=y;
Cut(x,y) 其中y为较浅的点 access(y),然后直接Fa[x]=x就好。
FindRoot 随便access一个点,再在splay上找深度最小的点就好

基本操作就这么多

前方高能

我们随便想几道题,我们就可以发现基于链的操作很简单,LCT硬上就可以了,打不打得出来那就是你问题了。

那么来道有难度的
wengwentao1:
给你一个根为1的树,让你支持加边、删边、查询某一个子树的size。

此处要维护子树信息
怎么搞?我们貌似只学过链。
我们观察,虚边实边(轻边重边)相对关系是不变的。在access操作中,只有少数的虚边变成了实边,相应的实边变成了虚边,整体树的形态是不变的。哪怕是Link-Cut也只是少部分改变了树的形态,总而言之轻边的信息我们完全可以维护一下。
我们对每个点算出其虚边儿子的size的和,我们称这个值为t_size,在重链上维护t_size的和,在虚实变换的时候,如图
这里写图片描述
一开始u,v为虚边,v,w为实边
然后虚实交换。在这个过程中,把v和w变成虚边。
也就是会把v的t_size += (w在splay上的t_size和+w所在的splay的大小)
然后把v和u变成实边,也就是会把v的t_size -= (u所在的splay的大小+u所在splay的大小)
然后把v,w给split开,把u,v给merge
于是完成了信息的维护。
想查询的话,直接access然后查询该点的值就好了。

是不是很神奇?

Top-tree

好,上面只需要子树的信息。
我们对虚边的信息都用一个int存下来。
如果我们要对虚数打标记呢?总不能每个虚儿子都遍历一次吧?太慢
我们需要知道所有的虚儿子,然后统一打标记。
于是我们每个节点就再用一个splay存它的虚儿子有哪些。
换言之就是把LCT维护的int替换成了splay。
同理只有在虚实变换的时候信息会改变,比较多细节好好讨论一下。
我把它叫做splay套splay!

这是Top-tree的一种打法
还有一种使用inner来解决问题,通过建立无用白点,从而把一棵树深度增大,树中每个点的儿子数不超过3。这样维护也比较简单,就是白点建立过于繁琐【加入的时候要讨论,删除的时候要讨论】,具体实现不知道怎么打,看论文吧。暂时先搁着。

ETT

DFS序听过吗?老朋友了。
括号序列听过吗?一对括号囊括的整个区间就是一个子树。
欧拉序听过吗?相同两个序号x之间夹着的就是x的某一个儿子的子树
也就是说,儿子的子树是一个欧拉序列括起来的。一个点儿子的子树我们可以通过把这段欧拉序列截取出来得到。

这里写图片描述

图中是一种形式的欧拉序,可见两个1之间夹着的就是2这个子树。
观察这个序列实际产生方式,其实就是一个环。这意味着每一段欧拉序如果能表示某个儿子【某颗子树】,它就是一个环。
那么我们用splay来维护欧拉序,Link、Cut都是把欧拉序的一段剪切到另外一段上【注意此处只能把一整颗子树给挪走,不能改变树的形态。不然欧拉序就会改变,信息就会出错】,对子树操作就是对欧拉序的一段打标记。注意信息的存储方式即可。
ETT十分完美地解决了子树信息的问题,但是不支持换根。

LCT+ETT

我们看Top-Tree太难打啦!
我们想给子树打标记,如果我们不用换根的话,我们会想到ETT,但是ETT不支持链操作。
如果我们硬是要链上乱搞,我们就结合一下LCT吧!
太过复杂而且没啥卵用,一时间没法理解,先搁着以后填坑。

0 0
原创粉丝点击