《浅谈一类基于线段树分治的信息维护算法》学习笔记

自己复习用,写的很随性,所以可能看不懂。

经典算法

维护一张 \(n\) 个点的简单无向图,有 \(m\) 次操作,支持加边删边,询问两点间连通性。

非常经典的线段树分治题,不再赘述。

算法1

有一张 \(n\) 个点 \(m\) 条边的无向图,第 \(i\) 个点只在第 \(L_i\)\(R_i\) 这段时间出现。你需要对于每个点 \(i\),判断是否存在一个时刻 \(x\) ,使得 \(i\)\(1\) 联通。

\(n\leq 2\times 10^5,m\leq 4\times 10^5\)

\(1\leq L_i\leq R_i\leq 2\times 10^5\)

考虑转化为,给每个时刻与 \(1\) 联通的连通块的点权 \(+1\)

给并查集的根打上 lazytag,撤销时给 tag 差分一下即可。

算法2

上面的题目要求信息有逆元,我们考虑如下加强:

连通块对 \(v\) 取 max,求连通块最大值。

考虑写出一个类似 Kruskal 重构树的东西,即每次合并新加一个节点,撤销删除并下放 tag 即可。

精细实现可以做到线性空间。

应用

不难发现对于序列问题可以直接使用如上算法,可以做到 \(O(n+(m\log q+q)\log n)\)

又发现我们来自并查集的 \(\log\) 实际上可以 \(O(1)\) 维护,所以可以做到单 \(\log\)

算法3

单点修改权值,单点查询权值。

我们考虑用二进制分组 \(+\) 线段树来维护(点信息表示前缀和)。

不难发现,此时所有操作均可 \(O(\log)\) 维护。

合并两个集合相当于单点插入一个数。

分裂两个集合相当于单点查、删末尾、下传 tag。

整体修改为给所有线段树打全局 tag。

单点修改需要对目标点到根节点上的所有 \(\log\) 个点的下传标记,修改,然后合并。

总复杂度 \(O(n+m\log q\log n+q\log^2 n)\)

可持久化

待学习。

posted @ 2025-02-07 14:58  sidekick257  阅读(34)  评论(0)    收藏  举报