直接上个图
ps(题目)
1 | 依照这个数据 画的图 |
1. 什么是可持久化
就是说 你要去访问之前的状态, 感觉有点像dp和哈希, 每个点的标号来决定一个状态
2. 主席树它能带来什么效果
就我自己感觉来说,就是两颗一模一样的树,不是完完全全复制,而是有选择的复制,从图也可以看出,好好看这张图的编号,它可以节省空间,节省时间,hjt大佬Orz
3. 我一开始最难接受的部分……
- 就是动态开点,引用& 的使用,但是如果在建造的时候不用引用,你会发现根本就改不了实际值,然后还得加上好多好多行代码来实现,没必要,
- 引用&:就是为了递归中更好修改每个节点的左右子树,对, 就这样, 接受它的存在
洛谷主席树
- 因为它的数值范围太大,需要离散化,这里用的是stl的unique
- 然后类似前缀和的思想,k < sumL , 就往左子树去,相反,就去右子树
- 再看看图
- 最后查询的时候不要去按原数值输出,因为它建立的时候是类似权值线段树,输出应该是离散化后的数值下标
- root[] : 每个i 都给它建立一颗树,但不需要每个点都建,而是有选择的开点 存数据,看图,类似i == 3 时 10号点的左子树是7 是i == 2 的版本,而它要存的是右子树,然后开点存11节点的数据,那么root[i], 就是每个版本的根节点的数值,这样能更好的管理;
1 |
|
可持久化数组
(模板题)
- 既然说道每个操作对应一个版本,那我们可以想到上一道题,主席树的root,就是来存每个根节点的值,
- 那这里我们直接更新root所对应树进行修改就ok了
- 询问的话 就把你要的第几个版本的树丢到query函数去
1 |
|
可持久化并查集
(模板)
- 其实思想还是和前面一样,在这里就分享一下怎么去更新父亲fa,高度deep
- 我们都知道每个cnt开出来的点都有一个独一无二的标号,所以只要你传进来了一个根节点标号root[i], 你就可以知道每个叶子节点的fa 和deep,进而你就可以修改呀,查询呀,都是很基本的操作,和上面大同小异
- 那么我感觉最难的就是这么去找父亲呢?如果还是用路径压缩,那还不是白忙活了,每次查找都要创造一个fa[i]数组,那会爆了,换一个用秩来结合,也就是高度矮的 移到 高的
类似这样(合并1 4,发现两个高度相同,任取一个就行)
相应的, 当发现合并完之后,你要检查一下在此之前是不是两个集合的高度相同,是的话,还要去更新它的deep,像上图的4那样 deep[4] ++;
1 |
|
ps: 在这里还得感谢AgOH大佬的讲解,Orz