离线分治算法
整体二分
算法相关
整体二分用于解决一些决策性单调的分治问题,其核心思想就是利用分治将同一个范围内的答案统一处理。
若问题满足以下性质则可以整体二分:
- 单个询问可以用二分解决(可二分性)。
- 修改对答案贡献互相独立,修改之间互不影响。
- 允许离线。
一般而言,我们要求整体二分是要求值域单调而定义域不一定单调的,本质上是关于值域的二分。
具体实现是我们二分答案的值域(一般是时间),然后每次使用 std :: vector 记录有哪些询问在当前值域中,分治时将询问集合按值域分为两组,并递归处理即可。
例题
P3527 [POI 2011] MET-Meteors
简要题意
环形加,问每个数第一次大于 \(p_i\) 的时间。
思路
单组询问可二分,操作相互独立,考虑整体二分。
考虑二分判定问题。有解的可能性随时间推移而增大,则时间作为一个单调域可以在其上整体二分。
因此我们只需要用 BIT 维护即可。
P2617 Dynamic Rankings
简要题意
单点修区间 \(k\) th。
思路
首先考虑弱化版:不带修。则单次询问可以二分,且询问相互独立,可以整体二分。
则带修版本我们只需要以 \(a_i\) 的值域作为整体二分的值域,在其上维护即可。
P1527 [国家集训队] 矩阵乘法
简要题意
静态矩阵第 \(k\) 小。
思路
和上一题相差不大,将整体二分中的数据结构改用二维树状数组维护即可。
P3332 [ZJOI2013] K 大数查询
简要题意
区间集合插入数字,区间集合并查询第 \(k\) 小。
思路
只需要在整体二分时维护线段树,每次只插入比当前二分的答案要小的数,判断其与 \(k\) 的大小关系即可。
P4602 [CTSC2018] 混合果汁
思路
只需要维护值域线段树,在上面记录有多少点,以及点的权值和即可。整体二分时的查询则是一个线段树二分。
CDQ 分治
CDQ 分治是处理偏序关系的利器。
一般统计点对 \((i, j)\) 的贡献,分治时分为三种统计:
- \(i, j \in [l, mid]\)
- \(i, j \in [mid + 1, r]\)
- \(i \in [l, mid], j \in [mid + 1, r]\)
前两种可以分治递归计算,也就是说我们的侧重点在于维护左区间对右区间的贡献。由于我们经常只留下一维不保证偏序关系,所以我们在该层分治中按最后一个属性排序即可让其满足单调性,而后我们通常用双指针 + 数据结构维护。
在当前层分治完之后,我们需要清空当前数据结构,这是因为 CDQ 分治中每一层的贡献计算相互独立。
CDQ 分治可以优化 dp,同时它还可以“化静为动”,将动态偏序问题转化为静态偏序问题。
例题
P3810 【模板】三维偏序(陌上花开)
思路
模板,但是有必要说细节。
先在 cdq 外按 \(a\) 排序,每次递归里面再按 \(b\) 排序,那么合并的时候只需要处理 \(c\) 的贡献即可。
由于偏序带等号,所以把多个相同三元组之间的贡献很容易算重(漏),为了简化细节,考虑合并所有相同三元组,将其个数当做其权值来计算。
P4093 [HEOI2016/TJOI2016] 序列
思路
设 \(dp_i\) 表示以 \(i\) 为结尾的答案,有转移:
转移条件是一个三维偏序的形式,可以 cdq 分治优化。
需要注意的是,统计左区间对右区间的贡献时要预先知道左区间的答案,所以要在算贡献之前递归完左区间。
P4390 [BalkanOI 2007] Mokia 摩基亚
简要题意
单点修改,矩阵求和。
思路
将“时间”作为一个偏序的维度,这样我们每次查询实际有贡献的是时间小于该次查询的修改,这十分符合偏序性质。同时我们把矩阵查询拆分为四个查询,套上 CDQ 分治模板即可。

浙公网安备 33010602011771号