【随笔浅谈】颜色段均摊算法
十分浅显,由很多内容没有提到。有空再来填坑!
std::set 维护颜色段
定义颜色段(广义):放在一起具有某一性质的一段区间。
构造
可以考虑用一个结构体来表示一个颜色段,一个结构体记录了该颜色段的左右端点,以及该颜色段的某信息。然后将这些结构体放入 std::set
中,std::set
内部按照区间的相对顺序排序。
下文的介绍,以维护具有相同颜色的一段区间为例。
split 分裂
有时候,对于一个颜色段,我们只需要访问它的其中一段信息即可。
这时候就需要分裂该颜色段了。
定义 函数:将 所在的颜色段 ,分裂成颜色段 与颜色段 ;并返回颜色段 在 std::set
中的位置。
区间操作
有时候,对于一个序列,我们需要访问一个区间 的信息。
根据分裂操作,就相当于是访问区间 中颜色段的信息,依次统计即可。
基于数据随机、区间推平 - 颜色段均摊算法
当一道题目同时保证「数据随机」、「具有区间推平操作」时,大量的区间推平会使得整个序列的势能一直维持在较小的范围内。
可以证明运用 std::set
维护颜色段的方法的时间复杂度为 。hqztrue 的证明。
例题选讲
1.【CF 896C】Willem, Chtholly and Seniorious
Description
给出一个长度为 的序列 ,你需要维护这个序列,共 次操作,共 种操作:
1 l r x
:对 ,令 。2 l r x
:对 ,令 。3 l r x
:求区间 内的第 小,数字相同算多次。4 l r x y
:求区间 内每个数字的 次方模 的值。
数据范围:,。
时空限制:。
Solution
该算法起源题。
- 操作 1:将区间 里所有颜色段的颜色加上 即可。
- 操作 2:将区间 里所有颜色段的颜色赋为 即可。
- 操作 3:访问区间 里的所有颜色段,提取出后排序,找到第一个前缀和 的颜色即可。
- 操作 4:访问区间 里的所有颜色段,将每个颜色段用快速幂统一统计即可。
基于操作影响势能 or 与势能无关 - 颜色段均摊算法
当一道题目保证「操作影响势能」或「操作与势能无关」时,则时间复杂度可以运用均摊分析法来测算。
例题选讲
1.【Luogu P2824】「HEOI2016/TJOI2016」排序
Description
给出一个 至 的排列,现在对这个排列序列进行 次局部排序,排序分为两种:
-
0 l r
:表示将区间 的数升序排序。 -
1 l r
:表示将区间 的数降序排序。
最后询问第 位置上的数字。
数据范围:。
时空限制:。
Solution
注意到给区间 内的点 升序 / 降序 排序,是赋予了一个区间有序的性质。
可以用权值线段树来维护一个有序区间内的权值信息,然后将这些有序的区间放入 std::set
中。
套用上述模板即可,不同点只是在于对权值线段树的处理:
- 对于 split 操作,线段树分裂即可;
- 对于区间排序,线段树合并即可;
- 对于查询操作,线段树上二分即可。
由于一次排序操作至多会进行两次线段树分裂,增加的点数是 的,故在整个过程中线段树的总节点个数为 级别的。
在区间排序中,由于每访问一个颜色段,就会将该颜色段删去,使得势能降低。
故总时间复杂度为 。
该做法支持多测 + 强制在线。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探