可持久化线段树总结
本文移植自个人的原博客(原文)
定义
主席树又称可持久化线段树,相对与普通的线段树,其解决的是各种不适用于结合律的区间问题,诸如区间第$K$大,区间种类个数等。
线段树的每个结点,保存的是这个区间含有的数字的性质的结合。
主席树的每个结点,保存的元素以元素大小为第一维位置,同时保证以区间为第二维位置,直接实现是$O(nlog^2n)$的时间空间复杂度,即每一个区间都要建一棵树,考虑每颗线段树的大小和形态是一样的,那么我们便可以利用主席树之间相互进行加减运算的性质,进行可持久化建树。
具体过程是按区间位置进行建树,每次插入新的数,只需要重新插入一条链,因为对于那些性质没有改变的前缀(如插入元素的位置是$3$,那么节点:$[1,2]$就没有必要改变),只需要重新调用皆可,否则利用原节点建一个新的节点(如插入元素的位置是$3$,那么节点:$[3,4]$的性质一定发生了改变,但又要保证原区间的该节点性质不变,那么便可以先将该节点粘过来,再在此基础上建一个新的节点,插入在当前根节点下),这样时间空间复杂度均降到了$O(nlogn)$(可持久化线段树按权值建树,其时间复杂度实际与权值范围有关(所以要离散化),本文全部以$n$代替)。
当然,这样实现也会导致整个数据结构实际上完全不是一棵树了,但是却仍满足每个节点最多有两个后继的限制,因此查询时只要调用$l−1,r$两个根节点即可。
相关题目
NEERC 2004 K小数
题目链接
题目描述
题解
实现与按权值维护的平衡树类似,直接递归查询即可。
|
SDOI2009 HH的项链
题目链接
题目描述
题解
对于每一个元素,记录其在数列内下一个种类相同的元素的位置(以 $to$ 数组表示),那么问题就转化为了求区间内有多少个元素的 $to$ 值大于查询的右区间位置,将 $to$ 数组插入到主席树中,直接建树求解即可。
|
动态排名系统
题目链接
题目描述
题解
本题为裸的带修改区间第$K$大,如果直接在例$1$的基础上修改,则会导致超时,因为每次修改都要修改$nlogn$个节点,即最坏情况下每一个根都要修改$log$个没有指向前面节点的节点。那么可以考虑,主席树维护的实际上是数列的前缀的性质,可以利用树状数组优化,即将原先的对于每一个新元素的前缀建树,改为对于树状数组中的前缀建树,那么修改时只要修改$log^2n$个节点即可。
|
国家集训队2011 数颜色
题目链接
题目描述
题解
同样是记录 $to$ 数组,对于修改操作,可以暴力求出修改后该位置 $to$ 的变化,考虑一下可能造成的在该元素前的元素的 $to$ 指针的变化即可(注意同样要修改主席树),详见代码。(对于$to$数组的查询和修改可以用平衡树优化)
|