线段树分治
线段树分治可以将“一段时间”的条件统筹处理。
一种理解方法是考虑暴力,在每个时间点将当前状态调整出来,线段树分治做的事情相当于将一段时间内都有效的信息统一处理,当这个信息不再满足的时候就撤销。
具体地,若一个条件(通常是可以用并查集维护的)在时间 \([l,r]\) 内有效,我们可以对时间轴开线段树,将这个区间其在拍在线段树的节点上,容易发现一个条件最多被拍成 \(O(\log n)\) 段,处理询问时只需 DFS,在进入一个节点的时候将这个区间的条件加入,退出一个节点的时候将这个节点的信息回退。
这种支持回退的数据结构一般为可撤销并查集。这类并查集在维护的过程中需要维护一个栈记录操作,且不能路径压缩,为保证复杂度必须按秩合并。
P5787 二分图 /【模板】线段树分治
题意
给定一张无向图,已知每条边的生效时间区间,对每个时间点判断这个图是否为二分图。
分析
判二分图的常见方法为黑白染色,这等价于用扩展域并查集维护。
考虑一个图已知的状态,对每条边的两个端点我们连反集,表示这两个点分别属于二分图的不同集合。在 DFS 的过程中如果发现某条边的两个点属于同一个集合就确定无解,可以在中途输出这个区间的答案。
P5227 [AHOI2013] 连通图
题意
给定一个无向图,\(q\) 次询问,每次给定一个边集(大小不超过 \(4\)),删去集合中的边,问新图是否联通。询问相互独立。
分析
一次询问删掉 \(O(1)\) 条边,等价于这次询问前和这次询问后这条边都是可用的。将每条线段能用的时间点拍到线段树上,正常线段树分治。
P4219 [BJOI2014] 大融合
题意
有一棵树,初始所有边都未连接。你需要维护图支持两种操作:
- 连接 \((u,v)\);
- 询问 \((u,v)\) 边的负载。
一条边的负载定义为:其所在的连通块经过它的简单路径的数量。
分析
将每条边能用的时间点拍到线段树上,做线段树分治。
注意询问的时候是不能用这条边的,但是我们想要知道这条边两条端点所在的连通块的大小(当然为了满足题设这两个点之前不能被连通),这是并查集能够胜任的。
cjx 管这个叫“千夫所指”。