线段树优化建图

Posted llmmkk 的尘歌壶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树优化建图相关的知识,希望对你有一定的参考价值。

在一类问题中,我们会使用时间复杂度和边数有关的算法,如【HNOI2019】校园旅行中的暴力算法,\\(O(n+m)\\) 的 Dijkstra,\\(O(n+m)\\) 的 tarjan 等,此时可能会由于边数太大而导致算法复杂度过大,此时的一个优化方向就是减少边数的规模,比如[【HNOI2019】校园旅行]中,我们充分利用题目条件的性质,将边分类然后只保留连通块的一颗生成树或基环树,将边数降至 \\(n\\)。而另一种常见的减少边规模的技巧就是线段树优化建图。

线段树优化建图

线段树优化建图的适用范围是连边和区间有关,比如一个区间内的点都向某个点连边,一个点向一个区间内的所有点连边,甚至一个区间内每个点向一个区间内每个点连边,这些边的规模是 \\(n^2\\) 的情况使用线段树优化建图之后边的规模就是 \\(n\\log n\\) 了。

区间向点连边

建出这样的图,然后区间向点连边只需要像正常线段树操作找到 \\(\\log\\) 个区间再连就可以了,如区间 \\([2,8]\\) 连向 \\(7\\)

点向区间连边

发现上面的图并不能适用,我们需要将边反向,

然后如果是 \\(7\\) 连向区间 \\([2,8]\\),就会是


区间向区间连边

于是我们发现需要两颗线段树,并且叶子结点是共用的,所以我们可以把第二张图转一下,建出这样的图:

这张图就可以支持点向区间以及区间向点的操作,但如果有区间连区间呢?比如有三个操作,\\(\\color{red}{1\\rightarrow[3,6]}\\)\\(\\color{blue}{[7,8]\\rightarrow 2}\\)\\(\\color{gold}{[3,6]\\rightarrow [7,8]}\\),然后连出来就是

发现如果出现区间向区间连边的情况,如果直接连边,边的规模会变到 \\(n\\log^2n\\)

这样看起来就像没有线段树优化的直接建图一样,并不优,所以对于区间向区间连边的情况,我们再采取一个措施,就是建一个虚点,将涉及到的区间向虚点连边而不是直接连向区间,这样每新建一个虚点,边数增加就也是 \\(\\log\\) 的了。那么就是:

这样,我们发现边的规模就可以减少到 \\(n\\log n\\),但一个点到另一个点经过的边数增多了,所以如果图要求有边权,线段树上的边权都应该设为 \\(0\\)


以上是关于线段树优化建图的主要内容,如果未能解决你的问题,请参考以下文章

线段树优化建图

线段树优化建图

CF786B Legacy 线段树优化建图

bzoj5017 [Snoi2017]炸弹 (线段树优化建图+)tarjan 缩点+拓扑排序

CF786B Legacy(线段树优化建图)

CF786B Legacy(线段树优化建图)