可持久化树套树 (细节) 笔记

假设已经会了树套树和可持久化权值线段树 (主席树)

昨天晚上在机房里面写,发现我有一些细节问题不是很懂,并且对这个玩意理解的也不太行

一些约定

有一个树套树,内外都是权值线段树。

对于一个外层树上的点 \(u\),称左右儿子为 \(ls(u),rs(u)\),并且套着一个内层树 \(T(u)\)\(T(u)\) 的根是 \(rt'(u)\)

对于一个内层树上的点 \(u\),称左右儿子为 \(ls'(u),rs'(u)\),并且维护了一些信息。

对于一个线段树,设位置 \(x\) 的影响路径为,从根一路找,找到单点 \(x\),经过的路径(包括根 \([1,n]\)\([x,x]\)

例如 \(n=5\) 时,\(x=2\) 的影响路径为 \([1,5],[1,3],[1,2],[2,2]\) 对应的点。

正片

有这样一个二维数点问题:加入一个点,询问矩形里点的信息(个数/和/max)。很明显可以树套树做。

这样的问题,如果要支持历史版本的询问,如何做?

即,我们要询问:如果只插入了前 \(i\) 个点,矩形信息。

考虑可持久化。相当于每个版本都有一个树套树。那首先我们肯定要把外层可持久化。

\(rt(i)\) 表示第 \(i\) 个版本的外层树的根。考虑 \(i-1\) 版本到 \(i\) 版本的变化,很明显是多了一个点 \((x,y)\)

根据树套树,我们需要在外层的树上找到 \(x\) 位置的影响路径。对于影响路径上的所有点,它们套的内层树 \(T\) 都要在 \(y\) 位置做插入。

现在我们要可持久化这个过程。类似主席树,用 path copy 的思想:在外层树上把 \(x\) 的影响路径给copy一份。对于路径上的每个点,要修改的那个儿子就递归做,不要修改的那个儿子直接继承原树。

考虑复制的时候怎么快速维护。设它影响路径上有个点 \(u\),我们把它复制到 \(u'\)。那么 \(T(u')\) 就是 \(T(u)\) 加上一个 \(y\) 位置的插入。

只有这个内层树操作是不好做的,剩下的操作都比较simple。考虑一下,我们相当于要支持:

  • 有若干颗树
  • 每次给 \(i,j,x\),令 \(j\) 这颗树为 \(i\) 这颗树插入一个 \(x\) 位置
  • 要求维护每棵树的信息

注意到这玩意也可以用可持久化做,把 \(i,j\) 看成版本就行了。

那我们内层也要维护一个可持久化树,来支持这个操作。

例题: bzoj3489

转换一下问题,设 \(pre,suf\) 表示前一个/后一个和当前相同的位置。问题变为:

有若干点 \((i,pre_i,suf_i)\),每次给 \(l,r\),求满足:\(i\in[l,r],pre_i<l,suf_i>r\) 的点中,最大的 \(a_i\)

注意到 \(pre\) 这一维是一个 \(<\),把它看成是版本,维护一个可持久化树套树。树套树里面维护 \((i,suf_i)\) 两维

然后就搞一个可持久化的树套树求矩形max就行了。

时空复杂度均为 \(O(n\log^2 n)\)

代码

posted @ 2021-09-07 18:49  Flandre-Zhu  阅读(145)  评论(0编辑  收藏  举报