离线分治算法

整体二分

算法相关

整体二分用于解决一些决策性单调的分治问题,其核心思想就是利用分治将同一个范围内的答案统一处理。

若问题满足以下性质则可以整体二分:

  • 单个询问可以用二分解决(可二分性)。
  • 修改对答案贡献互相独立,修改之间互不影响。
  • 允许离线。

一般而言,我们要求整体二分是要求值域单调而定义域不一定单调的,本质上是关于值域的二分。

具体实现是我们二分答案的值域(一般是时间),然后每次使用 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\) 为结尾的答案,有转移:

\[dp_i = \max_{j \in [1, i)} \{ dp_j \} + 1 (a_i \le \min \{ a_j, b_j \} \land \max \{ a_i, b_i \} \le a_j) \]

转移条件是一个三维偏序的形式,可以 cdq 分治优化。

需要注意的是,统计左区间对右区间的贡献时要预先知道左区间的答案,所以要在算贡献之前递归完左区间。

P4390 [BalkanOI 2007] Mokia 摩基亚

简要题意

单点修改,矩阵求和。

思路

将“时间”作为一个偏序的维度,这样我们每次查询实际有贡献的是时间小于该次查询的修改,这十分符合偏序性质。同时我们把矩阵查询拆分为四个查询,套上 CDQ 分治模板即可。

posted @ 2026-10-02 21:31  endswitch  阅读(3)  评论(0)    收藏  举报