码迷,mamicode.com
首页 > 其他好文 > 详细

并查集

时间:2017-11-01 16:36:15      阅读:250      评论:0      收藏:0      [点我收藏+]

标签:访问   不能   均衡   强制   题意   双向链表   本质   长度   超过   

按秩合并

  每次将秩小的合并到秩大的,若相同,秩加 1 。

  秩反应的是容纳水平, 秩越高, 容纳水平越高, 这样才能更加均衡地填满.

  每次只修改 $O(1)$ 的元素,可以快速撤销。

 

  HDU 5354

  分治 + 按秩合并并查集,判断删去任意一条边后,该图是否是二分图。 

 

路径压缩

  给序列,每次访问一个区间,若某点被访问过,则不访问这个点。

  类似地,给树,每次访问一条儿子 - 祖先路径,若某点被访问过,则不访问这个点。

  本质:给每个点有且仅有一个后继的结构,每次访问某一段,若某点被访问过,则不访问这个点。

  用并查集进行路径压缩,均摊线性。

 

  变:给树,每次访问某条路径,若某点被访问过,则不再访问。

  路径由两条儿子 - 祖先路径组成。

 

  经典模型:若干次区间赋值,每次将区间 [l, r] 赋值 w ,一个点最终的值为区间的值的最小值,求每个点最终的值。

  通过排序,路径压缩。

  优点:性价比高——跑得快、短。

 

  BZOJ 2054 

 

双向链表

  只支持删除的双向链表,本质路径压缩.

 

  BZOJ 3211

  区间开方, 区间求和.

  开方次数很小,暴力枚举区间 [l, r] 每个不等于 1 的位置开方,使用双向链表对这个结构进行维护。

  对查询,再维护树状数组。

’‘

妙用并查集

  「BZOJ 1854」「SCOI 2010」 游戏

  给 n(<= 100000) 对 {a, b} , 每对中选择一个, 求从 1 开始的最长值域连续段的长度.

  对值域建图。

  把每个值当作图中的一个点.

  对于点对 {a, b} , 将点 a 与点 b 进行连边.

  每条边可以配对一个点, 求最大的 x , 满足前 x 个点可以被不同的边进行配对.

 

  考虑一个连通块.

  如果这个连通块是一棵树, 那么可以对任意的 n-1 个点进行配对, 由于我们求从 1 开始的最长值域连续段, 所以对前 n-1 小的点进行配对, 最大的点不能被配对.

  如果这个连通块至少有一个环, 那么所有点都可以进行配对.

  我们只需要找到某个点 id , 它所在的连通块是一棵树, 且 id 是这个连通块中最大的点, 那么答案为 id-1 .

 

  「SCOI2016」 萌萌哒

  求有多少个无前导零的 $N(N\le 10^5)$ 位数 $A$ , 满足 $M(M\le 10^5)$ 个限制条件 $L~R~X~Y$ : $A[L+i] = A[X+i]$ .

  对 ST 表用并查集, 标记下传.

 

带权并查集 / 关系并查集

  「BZOJ 3376」 方块游戏

  题意

  给定 30000 个方块, q 次操作:

  M x y: 将标号为 x 的方块所在的堆, 叠到标号为 y 的方块所在的堆之上.

  C x:  求标号为 x 的方块下有多少个方块.

  分析

  带权并查集.

  两个在同一堆的方块在一个并查集内, f[x] 在 x 下.

  维护  f[x]:  x 在并查集的父亲.

      s[x]:  x 为代表元素, 集合的大小.

      w[x]:  x 与父亲之间有多少个方块.

 

  「BZOJ 2303」「APOI 2011」方格染色

  题意

  在 n * m 的方格中, 每个格子要填上 0 或 1, 且满足任意一个四方格中, 有 1 个 1 或者 3 个 1 .

  已知某些格子中填的数, 求有多少种合法的填法.

  n, m <= 10 ^ 6 .

  分析

  探究合法填法的一些性质.

  a[x, y] = a[x-1, y-1] ^ a[x, y-1] ^ a[x-1, y] ^ 1 .

  将 a[2 ~ x][2 ~ y] 异或起来, 可以得到 a[x, y] = a[1, 1] ^ a[x, 1] ^ a[1, y] ^ [(n-1) * (m-1) 为奇数] .

  假如我们能够确定第一行, 第一列, 那么所有的格子都确定了.

  枚举 a[1, 1] 的取值, 那么限制条件变为二元的限制条件 a[x, 1] ^ a[1, y] = c .

  我们将 (x, 1) 与 (1, y) 的关系通过并查集维护, 最后查询 2 ^ {连通块个数 - 1} .

 

  BZOJ 1202」狡猾的商人

  f[x] < x .

  维护 b[x] = sum(f[x], f[x]+1, ..., x) .

 

Kruskal 与 Kruskal重构树

  给 n 点, m 带权边的无向图,在线求在所有边权不超过 d 的边的作用下,某个点或某两个点的连通性信息。

  例子:可持久化并查集。n 个点, 支持连边, 和查询在前 t 次操作下, 某两个点是否连通。这个例子隐藏起了时间这一维,将时间量化就可以完成转化: 在时刻 t 将某两个点连边, 就相当于 x 与 y 之间存在一条边, 边权为 t .

 

  将边权从小到大进行排序, 不断加边, 用并查集进行维护.

  将并查集的功能拓展, 支持维护历史信息.

  按秩合并.

  多记录一个 w 数组, 在并查集中, 当点 x 的父亲指向点 y 的时候, 记录 w[x] = 边权 .

  在查找一个节点 x 在不超过 d 的边权的作用下的并查集时, 只需要将 x 在并查集中从下往上跳, 直到恰好跳到满足 w[x] > d 时停止, 就能找到集合的代表元素.

  如果需要查询连通块内的信息, 进行可持久化线段树合并, 对每个点开一个 map 来记录所有的根.

 

  Kruskal 重构树。

  每次合并的时候, 新建点 cur , 将两个代表元素的父亲指向当前这个新建点 cur .

  找 x 在不超过 d 的边权的作用下的代表元素时, 不能直接往上跳, 改用树上倍增.

  如果需要查询连通块内的信息, 可以进行可持久化线段树合并, 这时候每个点对应的根唯一, 不再需要开 map . 或者可以将 Kruskal 重构树进行 dfs 序剖分, 转化为序列的问题.

 

  比较一下两种写法的优缺点:

  自己的写法速度较快, 查询代表元素可以直接查询, 不支持 dfs 序剖分, 需要开 map .

  Kruskal重构树速度较慢, 查询代表元素需要树上倍增, 支持 dfs 序剖分, 不需要开 map .

 

  「BZOJ 3551」 Peaks

 

  BZOJ 4668」冷战

  题意

  两种操作:

  0 x y  将 x 和 y 进行连边.

  1 x y  询问 x 和 y 在什么时候刚刚连通.

  n, m <= 500000, 强制在线.

  分析

  按秩合并.

  维护信息 w[x] 表示 x 合并到 f[x] 的时间.

  对于查询暴力找 LCA , 并求路径的 w[x] 的最大值 (其实必然是最上面的两个点中的一个) .

 

LCA

  离线算法, 用于求出若干组点 (x, y) 的 LCA , 效率极高.

  先将所有询问读入, 然后对树进行 DFS . 回溯的过程中将 f[son] 赋为 cur ; 访问完一个节点时进行查询, 对于 (cur, x) , 若 x 已被访问, 那么查询 x 在并查集中的祖先.

并查集

标签:访问   不能   均衡   强制   题意   双向链表   本质   长度   超过   

原文地址:http://www.cnblogs.com/Sdchr/p/7614530.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!