一个用于求解某些离线区间问题的方法,比树套树和主席树码量更小。
对于可以依次二分求解的多个区间问题,我们也可以统一二分,每次二分时统一取 mid,将满足要求(即 check(mid) == true)的询问与不满足要求的询问分开,在递归在其对应的区间上二分,相对于每个询问分别二分优势在于只用进行一次预处理。
实现
例题:Luogu P3834 【模板】可持久化线段树 2
这是可持久化线段树的模板题,但是可以用整体二分做。
先考虑朴素二分。我们二分答案 \(mid\),将小于等于 \(mid\) 的数放在树状数组上,并查询 \(l\) 到 \(r\) 中这样的数的数量是否大于等于 \(k\),并调整区间。
这种做法有一个优化:每次向右调整区间后,我们将询问的 \(k\) 减去 \(l\) 到 \(r\) 小于等于 \(mid\) 的数的数量。
但这样依然会 TLE。
我们考虑将预处理过程进行合并,并利用整体二分的思想,预处理一次,查询所有询问是否满足要求,并将询问分成两类,递归处理。
这样复杂度就降到了 \(O(n\log^2 n)\)。
由此可见,整体二分对于主席树之类的在线算法除了码量小以外,时空上没有任何优势,因此需谨慎使用。
拓展
修改操作
整体二分有时支持修改操作。
可以将修改操作拆成两个操作:减少一个数与增加一个数,二分时将这两种询问分别放到对应的区间内就可以了。
注意事项
- 整体二分的时间复杂度是 \(O(n\log^2 n)\) 的,并且常数巨大。
- 一定不要搞混整体二分的二分对象,时间轴,原数组下标和询问的下标。