并查集小记

前言

考前复建一下经典知识点,补充一下带权并查集和扩展域并查集。

分析

普通并查集

先看一个经典问题:

\(n\) 个数,\(n\) 个集合,每个数一开始对应一个集合,有两种操作:

1 x y 合并 \(x\)\(y\) 所在的集合。

2 x y 询问 \(x,y\) 是否在同一个集合。

将每个集合赋予树形结构,若干个集合便成为了森林。

考虑维护 \(f_i\)\(i\) 所在集合中 \(i\) 的祖先。

定义一个函数 \(\operatorname{find}(i)\) 代表查询 \(i\) 所在集合的根节点。

对于 \(\operatorname{find}(i)\) 函数的实现,考虑使 \(i\) 在树上不断向上跳即可。

对于 \(1\) 操作,判断 \(\operatorname{find}(x)=\operatorname{find}(y)\) 即可。

对于 \(2\) 操作,显然是合并两棵树,直接将 \(x\) 所在树的根接到 \(y\) 所在树的根上即可。

但是考虑到树的形态最坏是一条链,只是暴力跳的话复杂度会很劣。

引入并查集的两种优化:

  1. 路径压缩优化:结合上面的分析,对于一棵树,我们只关心这颗树的根节点是谁,而不关心这一结构的具体形态,那么在访问 \(\operatorname{find}(i)\) 时,将 \(i\) 的父亲直接指向树根即可,单次查询均摊复杂度 \(\mathrm{O}(\log n)\)

  2. 按秩合并优化:将「秩」定义为树的深度或树的大小,将「秩」记录在根节点上,每次合并将「秩」小的合并到「秩」大的。注意到当 「秩」定义为树的大小时,也被称为「启发式合并」,具体意思是指将「小的结构」合并到「大的结构」中,单次操作均摊复杂度 \(\mathrm{O}(\log n)\)

  3. 同时使用两种优化的并查集复杂度为 \(\mathrm{O}(\alpha(n))\)

集合中单个元素的删除和移动:对于元素 \(x\),创立 \(x\) 的副本 \(x'\),若删除,令 \(f_{x'}=x'\),移动同理,同时访问 \(x\) 时,将 \(x\) 导向 \(x'\)

带权并查集

考虑维护 \(x\)\(f_x\) 的信息,在路径压缩的时候通过与 \(f_x\) 到其祖先维护的信息进行整合,最终储存 \(x\) 到根节点的信息,被称为带权的并查集。

扩展域并查集

将原来的单点,扩展为若干状态,在这些状态中进行并查集操作。

例题

P1955 先对元素进行离散化,考虑分开处理元素相等和不相等的情况,体现为先通过 \(1\) 操作合并相等元素,通过 \(2\) 操作判定元素是否相等。

P2391 倒序处理询问,显然每个点只会染一次色,考虑用并查集维护连续的一段 \([l,r]\),而这段的根节点是 \(r\)。暴力染色,若遇到已经染色的节点,查询该节点的祖先,跳过去即可。在染色的过程中不断合并已经染色的区间。

UVA1316 对于更加贵的商品,优先放置,且放置在离过期时间更近的地方,与上题类似,维护区间,将 \([l,r]\) 的根节点设为 \(l\),判断 \(1\sim d_i\) 是否有空位即代表 \([1,d_i]\) 尚未被合并成一个大区间。

P1196 带权并查集板子,记录 \(d_x\) 代表 \(x\) 到根节点的距离,对于答案即为 \(d_y-d_x-1\)

P5937

做法 \(1\)

考虑将给出的条件进行转化。

定义 \(sum_i\)\([1,i]\)\(1\) 个数的奇偶性。

\([i,j]\) 有偶数个 \(1\) 即为 \(sum_{l-1}=sum_r\),有奇数个 \(1\) 即为 \(sum_{l-1}\neq sum_r\)

定义 \(d_x\)\(x\) 与根节点的奇偶性是否相等,若 \(x,y\) 在同一个集合,此时 \(d_x\ \operatorname{xor}\ d_y\) 的取值即可判定 \(x,y\) 的奇偶性是否相等。

合并集合时,记 \(p,q\)\(x,y\) 所在集合的根节点,不妨令 \(x\) 集合合并到 \(y\) 集合,可以推导出 \(sum_{x}\ \operatorname{xor}\ sum_y=d_x\ \operatorname{xor}\ d_p\ \operatorname{xor} \ d_y\)

因此 \(d_p=sum_{x}\ \operatorname{xor}\ sum_y\ \operatorname{xor}\ d_x\ \operatorname{xor}\ d_y\)。更新 \(d_p\) 并合并即可。

做法 \(2\)

考虑将 \(i\) 拆为两个节点 \(i_e\)\(i_o\) 代表 \(sum_i=0/1\)

有偶数个 \(1\) 则代表 \(sum_{l-1}=0\)\(sum_{r}=0\)\(sum_{l-1}=1\)\(sum_{r}=1\) 可以互相推出,合并 \((l-1)_{e}\)\(r_e\)\((l-1)_{o}\)\(r_o\)

有奇数个 \(1\) 同理合并 \((l-1)_{e}\)\(r_o\)\((l-1)_{o}\)\(r_e\)

判定进行操作前是否矛盾即可。

posted @ 2023-08-07 18:52  _shy  阅读(26)  评论(0编辑  收藏  举报