区间/树链染色问题
给定一个 个数的序列, 个操作:每次对一个区间进行染色,其中染过的位置不用再染。
其中
暴力模拟的时间复杂度是 ,显然不能接受。考虑这个暴力慢在哪里?
暴力算法每次都要遍历一遍区间,由于染过的地方不能再染,所以暴力在已经染过的地方花费了大量时间,有没有办法排除这些 冗余 呢?
我们可以用并查集。
记 表示位置 自己及其后面第一个没有染色的地方,假设 这个位置被染色了,就将 。在区间染色时,只需将循环这么写即可。
for(int i = l; i <= r; i = f[i]) {//在区间[l,r]染色 ... }
经过这样处理,每次跳到的位置都是没有染色的地方,于是不管 有多大,最多只会染色 次,于是时间复杂度就被降低到了 .
原题:白雪皑皑
这类题目还有一种变式:
个数,每次对 区间进行染色操作,可以覆盖掉已经染色的区域,问最后数列长什么样?
照题目来看,如果区间 被染了蓝色,再在区间 上染红色,最后这个区间应该是红色的,假如我们将这个过程倒过来:在 上染红色后,再染蓝色就是无效的,和上一题 “染过的地方不能重复染” 有点像,推广到一般情况也没有问题。所以只需将整个过程倒过来就和上一题一模一样了。
上述是序列上的情况,接下来讨论树链上的情况。
其实是大同小异的,我们只需记录每个节点的父亲,再将深度大的向上跳,剩下的就和序列上的一模一样了。
例题:数列
经过一些简单的转化就变成对树链上的每一条边赋值(已经赋过的不用赋),由于是边比较特殊,设 表示从 向上跳,最远可以跳到的点,即中间的边全部经过赋值。每次对一个点赋值后,将 即可。
来总结一下这种问题的指导思想:
- 排除冗余:由于染过的地方没有必要再染,所以使用并查集跳过大大优化了时间复杂度。
- 与倍增的联系:一般来说,一个个跳导致超时,要么考虑倍增,要么考虑并查集,其中倍增可以处理静态的问题,这和 有点像;但是并查集可以处理动态问题。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效