yang-xi-jie-mi-zheng-ti-er-fen
详细揭秘 整体二分
考虑这样一个问题:
- 给你一个序列,每次查询区间 kth。
如果你不会主席树,你可能会考虑二分答案:二分一个 ,看看它在区间中的 rank,与 比较。
这样子单次暴力是线性对数的,不太妙。问题出在哪里呢?你发现每次找 rank 是线性的,很慢。
我们把多个询问放在一起跑二分,即 整体二分,具体的:
-
用类似二分答案的思想,确定一些询问的答案区间 。假设我们现在正在解决答案在 内的询问。
-
二分 ,将答案在 和 的两类询问分开。
如何分开这两类询问?类似地,我们比较 在每个询问的区间中的 rank 和这个询问的 的大小。
现在这个 rank 要怎么找?你想要知道在序列上一个区间 内有多少数 。
注意这里只需要考虑原序列中值域在 中的数,那么把这些数中比 小的数拉出来,
将它们在序列上的位置 ,查询 的和就是你想要的。
询问分开了,那么我们递归下去直到 ,那么相当于二分答案结束了。注意分到右边的询问的 要减 rank。
这样每一层复杂度是 的,总复杂度为线性对数。
例题:
相当于二分答案时间,看该站在这个时间前是否完成任务。
每场陨石雨相当于区间修改,每次只执行 的陨石雨(区间加),
检验每个站点的值是否已经满足条件即可,也就是单点查询。
原题条件等价于每个连通块大小为偶数,这里不证,不是本文重点。
随着时间推移,答案肯定越来越优,也就是答案具有单调性。维护连通块肯定是用并查集了。
考虑单次二分答案的算法。对于时间 的询问,我们二分一个权值 ,然后加入所有时间 ,权值 的边,看一下是否所有连通块都是偶数。
现在变成整体二分。分治存当前处理的时间区间 和对应答案区间 。
设 。考虑将时间区间拆成两部分,第一部分的答案在 中,另一部分答案在 中。
在进入这层分治前用并查集内维护好权值 且时间 的所有边。现在我们向并查集内加入权值 ,时间 的边。
这样并查集里就有权值 ,时间 的边。这和我们单次二分要求的范围很类似了,接下来继续扩展:
- 依次加入时间 ,权值 的边,直到满足所有连通块都是偶数。
满足条件就可以停下来了,现在我们找到了一个分界线 ,满足时间 的都没办法只用 的边满足条件,而时间 的都能用 的边满足条件。这就说明,时间 的答案都在 中,时间 的答案在 中。
分治下去即可。注意需要维持进入这层分治前用并查集内维护好权值 且时间 的所有边。
需要支持并查集的撤销,用可撤销的并查集即可。
复杂度会发现每一层加边的数量加起来都是线性,所以复杂度 。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现