并查集

并查集有普通并查集,拓展域并查集,带权并查集这几种.

所有并查集的初始化都是初始爹都是自己.

并查集支持路径压缩和按秩合并两种合并方法.

橙王

路径压缩

由于路径压缩是查询的时候顺带压缩了一下,时间复杂度比较玄学,但是肯定比 $O(\log n)$ 要低.

按秩合并

并查集的另一种合并操作就是按秩合并,这样的并查集会因为一个size而控制树高不会超过 $\log n$ 的高度.

而且,这样的合并是一开始就写好固定了的,也就是支持可持久化(使用主席树维护即可)

普通并查集

一个元素的父节点变成另一个元素.用于检查某些元素在不在一个集合里面.

并查集支持维护区间,用法是一段序列的头和更靠右的合并,保证区间末尾一定是并查集的头,这样可以保证时间复杂度O(n),因为每一个数最多被合并一次.

拓展域并查集(种类并查集)

就是有两个及以上的并查集一起操作.比如,要求原有朋友关系的基础上添加一种新关系叫敌人关系,满足”敌人的敌人是朋友”,就可以拓展一个并查集,开到二倍空间.

实战就是,假设A和B是敌人,就合并A+n和B+n,假如B原先有敌人了那就合并朋友一个人和他敌人的敌人.

敌人本质上还是一个并查集.

带权并查集

并查集加个权重.比较灵活,维护的东西也比较多变,不好讲.

举例:给哪个学生比哪个学生多考几分,问谁和谁之间的分数差,就可以维护并查集叶节点和根节点的分数差关系.

魔改并查集

有的时候会让写一种奇怪的数据结构,支持某个节点的孩子并到节点的爹那里,同时后续操作还可能让某些节点继续并到该节点.

这类题的特征是:

  1. 支持查询一个节点的爹
  2. 盒子装球,合并盒子之后一个是空的,于是接着装球

我们把所有节点都看作一个点,于是他就是普通并查集.但是如何解决空盒子的问题?
建立一个映射,在并查集上动态开点,标记新开的点是原来被合并的点即可. 同时size啥的就很好维护了.

实战

  1. p5937,维护一个01组成的序列,给定一个区间,请你判断以下话语的正确性.如(1 2 odd 3 4 even)给定区间首尾.

    对于区间的题考虑如下转化:
    区间[l,r]可以转化为区间[0,l-1]和区间[0,r]的性质.
    然后再由于奇偶性的传递可以维护一个种类并查集.

  2. NOI食物链问题:

    维护三个并查集,表达的是吃与被吃的关系.
    如何表达他们是同级的呢?A不吃B而且B不吃A,或者直接查他们是不是一个集合
    如何表达吃的关系呢?直接维护并查集,A吃B抽象成A的上级就是B+n(不同群系,不同并查集)
    这样就得到了一个循环的样子:群系ABC三个并查集,同级就直接合并
    吃的关系就opt1合并opt2+mxx表示A群系的opt1和opt2+mxx是一级的,由于opt2+mxx是B群系所以体现了opt1吃opt2
    注意初始化并查集直接原数存就好
    注意先判断是不是真话再合并防止出现环的情况

  3. ATabc279f 盒子,写一个程序支持维护以下操作:1把一个新球放到某个盒子里2把a盒子里面的所有球放到b盒子里面3查询某个球属于某个盒子.

    并查集维护,关于某个盒子放到另一个盒子里面的情况可以通过开点的方法解决.(注意,点和箱子都应该看成点)