「笔记」线段树分治
写在前面
某培训机构某天的考试题出现了板子= =
于是简单写下。
模型
有这样的一种模型:
- 给定一些仅在 给定时间范围 内有效的操作。
- 询问某个时间点所有操作的贡献。
考虑离线操作,对时间轴建立线段树,将每个操作转化为线段树上的区间标记操作。
查询时遍历整棵线段树,到达每个节点时执行相应的操作,到达叶节点统计贡献,回溯时撤销操作的影响
模板题
P5787 二分图 /【模板】线段树分治
给定 \(n\) 个节点,有 \(m\) 条出现一段时间后后消失的边,第 \(i\) 条边 \((x_i,y_i)\) 的存在时间为 \([l_i,r_i]\)。
给定参数 \(k\),判断 \(1\sim k\) 内每个时刻时,整个图是不是二分图。
\(n,k = 10^5\),\(m=2\times 10^5\),\(1\le u_i,v_i\le n\),\(0\le l\le r\le k\)。
先考虑所有 \(r_i = k\) 的情况,即仅有加边操作,所有的边出现后不消失。
判断二分图,想到这个题:P1525 关押罪犯
考虑使用扩展域并查集进行维护。
具体地,将点 \(i\) 拆成点 \(i\) 和 \(i+n\),分别表示在同一独立集,与不在同一独立集。
对于一条边 \((x_i,y_i)\),将 \(x_i\) 与 \(y_i+n\) 合并,\(x_i+n\) 与 \(y_i\) 合并。
在加入一条边 \((x_i,y_i)\) 之前,若发现 \(x_i,y_i\) 在同一并查集中,则加入该边后相当于出现一个奇环,破坏了二分图的结构,之后再加任意数量的边都不为二分图。
再考虑消失的限制,并找不到什么可简单维护的方式。
考虑线段树分治,对时间轴建立线段树。
维护区间内存在的边集,用 vector 进行维护。
查询时从根节点出发开始遍历,递归处理时将当前节点存在的边进行合并,判断是否为二分图。
若到达某个点是不为二分图,则该点维护的时间区间内原图均不为二分图。
到达叶节点时,若仍为二分图,输出 Yes。
回溯时,发现并查集并不支持删除操作。
考虑使用一个栈记录下对并查集的操作,将父子关系再改回去。
则不可使用路径压缩,否则操作次数爆炸,为保证复杂度,应进行按秩合并。
注意扩展域并查集对空间的需求。
总复杂度 \(O(m\log n\log k)\)。
loj 121. 「离线可过」动态图连通性
给定 \(n\) 个节点,初始时图中没有边。有 \(m\) 次操作:
- 加入一条不存在的边。
- 删除一条存在的边。
- 查询给定点对是否连通。
\(1\le n\le 5000\),\(1\le m\le 5\times 10^5\)。
感觉这个比上面的还板子= =
大致思路同上,使用可撤销并查集维护连通性即可。
深入到叶节点时回答对应时刻的询问。
复杂度 \(O(m\log m\log n)\)。