「笔记」线段树分治

写在前面

某培训机构某天的考试题出现了板子= =
于是简单写下。

模型

有这样的一种模型:

  1. 给定一些仅在 给定时间范围 内有效的操作。
  2. 询问某个时间点所有操作的贡献。

考虑离线操作,对时间轴建立线段树,将每个操作转化为线段树上的区间标记操作。
查询时遍历整棵线段树,到达每个节点时执行相应的操作,到达叶节点统计贡献,回溯时撤销操作的影响

模板题

P5787 二分图 /【模板】线段树分治

原题面:Luogu darkbzoj

给定 \(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)\)

代码:P5787 二分图 /【模板】线段树分治

loj 121. 「离线可过」动态图连通性

给定 \(n\) 个节点,初始时图中没有边。有 \(m\) 次操作:

  1. 加入一条不存在的边。
  2. 删除一条存在的边。
  3. 查询给定点对是否连通。

\(1\le n\le 5000\)\(1\le m\le 5\times 10^5\)

感觉这个比上面的还板子= =

大致思路同上,使用可撤销并查集维护连通性即可。
深入到叶节点时回答对应时刻的询问。
复杂度 \(O(m\log m\log n)\)

代码:Loj 121. 「离线可过」动态图连通性

写在最后

参考:题解 P5787 【二分图 _【模板】线段树分治】 - xht37 的洛谷博客

posted @ 2020-11-02 17:01  Luckyblock  阅读(612)  评论(1编辑  收藏  举报