线段树分治时间学习笔记
由于CF做到了题目 Lenient Vertex Cover , 故有此文。
线段树分治,是一种用于离线处理修改或询问是在时间轴上的问题,在时间轴上建立线段树,将操作分摊到每个线段树的节点上的离线数据结构。
适用范围:
1.允许离线
2.操作或询问在时间轴中的一段区间生效(有时候需要很巧妙的时空转化或这人造时间轴)
3.操作易于添加,难于删除,但不难按顺序“撤回”,或是可持久化。
4.时间轴上点是有限的,或是可离散化的。
通常地,1e9以上的数量级一般会认为是“无限”的。
模板题: 二分图
给你一个图,每条边会在某段时间 存在 , 判断每个时刻该图是否为二分图 。
对于“加边”操作很好处理,使用扩展域并查集维护即可。
现在考虑不是“删边”,而是把这条边”放“到一段它存在时间轴上,在线段树对应的时间轴上的 个区间中,这样线段树的每个点都对应着一段时间里存在的边,每个时刻存在的边实际上就是所有根到该叶子的边的并。
于是我们最后遍历一遍线段树,处理这些询问,如下:
1 进行该点的所有操作(合并并查集,维护目前是不是二分图)
2 递归左右儿子,若为叶子,统计答案 。
3 撤回所有操作,回溯。
由于需要“撤回”,所以使用按秩合并即可,最后 倒序 撤回所有操作即可。
时间复杂度 ,小常数,通常 1s 能无伤 1e6 。
至于为啥名字里有线段树的东西是小常数,,,因为没有上传下放 等函数,并查集的常数也很小。
一些本质也是模板的题
题意:问一个图是否存在一个点覆盖使得最多有一条边被覆盖了两个端点。
题意可以转化为该图是否可以在删1条边后成为二分图, 建立时间轴使得每条边恰好在某一时刻不存在即可,然后变成模板题。
题意:多次询问删去某些边后图是否联通,每次删去的边集
将对应的边转成在时间轴上的某个点不存在即可变成模板,判断并查集树形结构中根的即可判断图是否连通。
都是判断删除某些边转化为“时间轴”上的问题。
一些不那么板的题
题意:定义扩展集 为不断执行一下操作后的 ,
支持加点和删点 ,
对于这种“极大扩展集”的套路:将 看作边 , 那么构成的图是二分图,一个点能被扩展的条件是存在这条边对应的题意中的三条边将两个点链接,那么可以连接该边,最终图中的边数即为答案,那么一个大小为 的连通块产生的贡献为 。
那么一条边合并一个 的贡献就是 。
使用并查集维护每个连通块两边的点数即可。
题意:会在某些时候加入边,边带有颜色,要求修改边后每种颜色都是二分图。若不是,则不修改这条边。
求最后每次修改是否被加进去了。
首先和模板题一样,只是开100个并查集。
每条边的每种颜色的很明显是一个区间,直到下一次染色,对这个区间加边即可,但是需要在走到叶子时判断一下这个是否有效,记录即可。
本质是把一条边拆成两次修改和一次询问。
不板的题
题意:
有一排 家商店,每家商店有固定售卖物品 。
每天 会发生一些事件:
1.某家商店 进货
2.某人将在 中购买 天内的物品,或固定物品,他想要购买物品的 最大,求这个值。
其实是一种变相“二维双限制异或最大值” ? ,可以使用树状数组套主席 , 也可建“伪Trie”通过整体二分解决。
这其实是一道“区间查询、单点修改”的线段树分治,对于这类题目,分治方如下:
-
建立时间轴上的线段树
-
将询问以线段树的方式下发到每个点上
-
将包括该单点修改的线段树上的 个节点打上对应标记。
-
遍历线段树,完成该点的所有操作后更新所有这个点上的区间、再撤回、继续进行递归儿子。
-
(此题略有不同,本身的题目可以通过线段树的“push up”将区间信息传上来,但是本题的询问是带有额外限制的,不好大量维护。)
对于本题,先用可持久化 查一遍固定物品的最大值,然后只用考虑在时间内且在空间内的物品。
然后按照上面的方式遍历线段树,用可持久化 进行区间查。
然后发现时间复杂度不是很对,
线段树分治的复杂度实际上是一种均摊复杂度,每个操作最多被划分成 个操作。
于是我们要保证每个点的复杂度是只和区间中的操作次数严格相关的。
在该题中、将被修改的商店离散化,二分求出对应区间即可。
时间复杂度
好题,写了篇题解
本文已经结束了。本文作者:ღꦿ࿐(DeepSea),转载请注明原文链接:https://www.cnblogs.com/Dreamerkk/p/17970970,谢谢你的阅读或转载!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步