可持久化数据结构 学习笔记

对了,200 blogs 祭。没想到是这么一篇揭露我大菜鸡水平的 blog。

主席树

一年前就学过了,到现在才开始系统学可持久化……都快要高一了才开始学这玩意,我真是 114514 流选手。

需要做的是,每次修改都不直接修改原来节点上的值,需要新建副本存下新值,使得可以任意访问任一历史版本。

这个就有这样一个思想:每次修改,不论是单点还是区间,由于复杂度被保证,只有对数级别的点被修改了。于是我们就把有修改的点给新建了,然后新建的所有点要连向不修改的原来节点,这些个节点在新旧版本中共用。脑补一下,单点的情况就是旁边多出来一条链,然后往里连。这样想要访问哪个版本,就从对应的根往下走即可。(烦死了说不清,会的都会)

需要注意的是,主席树区间修改不能用懒标记(因为往下推的时候可能会推到共用的儿子,就出锅了),只能标记永久化

值得一题的是,主席树的空间是和动态开点一样分析的,是线对。如果按照原来的每个节点都额外存表示的区间的话,那可能会被卡,所以我做了一个伟大的决定:废除这个陋习!就递归往下走的时候顺便记录即可,还可以有效解决空节点没有存区间的问题。

模板:https://www.luogu.com.cn/record/47290779

可持久化数组

直接用主席树实现。

你可能要问,这数组既不需要区间修改,又不需要区间查询,拿主席树这种区间数据结构维护不是浪费了吗?再者,非叶子节点里面都不存信息,这不更离谱了吗?那我要告诉你,树形结构起着支撑与平衡的作用。甚至可能可以证明用主席树实现可持久化数组是最优的。

模板:https://www.luogu.com.cn/record/47291192

可持久化并查集

就维护可持久化数组就可以了。路径压缩的复杂度是均摊的,在可持久化中会失效(比如反复访问一个回答询问很慢的历史版本,就 GG 了)。所以只能用启发式合并 / 按秩合并实时保持平衡。

那么就需要维护父亲和子树大小两个数组,可以开两个主席树,当然也可以写到一起节省空间。

模板:https://www.luogu.com.cn/record/47292506

posted @ 2021-03-02 23:56  ycx060617  阅读(94)  评论(0编辑  收藏  举报