作者会把自己学习时遇到的一些疑问回答,尽量写的详细、合理,让更多人能够理解这个算法。
简介
整体二分作为一种离线算法,作用其实并不是很广泛。但是它能够以较短的码量、较低的思维难度解决一些其他算法无法或者难以解决的问题,确实不失为一种优秀的算法。更重要的是算法思想:统一解决问题,或者换句话说,全部输入,离线一次性解决一切。这种思想确实可以拓展到更多内容上。
内容
顾名思义,整体二分是处理这样一种问题:可以使用二分法解决,但是对于每一个询问都进行一次二分时间复杂度无法接受的问题。这时候,整体二分就诞生了:它先将所有操作读入,然后进行一个统一的二分,或者说:分治。因为是一次性处理所有询问、修改,因此这种算法被称为:整体二分。
先回忆一下普通二分的内容:当询问和操作满足单调性时,每次查找一个中间点与当前询问作比较,决定是接着往哪个方向寻找。这样子区间长度每次减半,时间复杂度是优秀的 \(O(\log_2n)\)。
拓展到整体二分上,我们相当于是同时对每一个询问查找。每一次二分,我们会有一个值域区间,一个当前需要处理的操作序列。我们接着来比较每个操作以及中点 mid,也就是说,对于当前的值域区间,所有询问操作会被分成两个部分:目标在左区间的,以及目标在右区间的。而为了接着处理这些询问,我们相当于是要接着分别处理两个区间的询问,一直递归下去。当然,如果左区间或者右区间没有操作序列,那自然就不需要接着操作了,直接返回即可。如果当前值域只剩下一个点了,也就是我们已经递归到终点了,直接存下答案即可。
具体实现的话,我们需要一个 \(solve\) 函数,有四个参数:\(ql,qr,l,r\) ,分别表示当前操作序列的左右端点,以及当前值域的左右端点。操作序列之所以会有一个区间,是因为处理操作时会把当前区间分成两部分,为了方便就直接在当前区间分开,再递归处理下去。
应该能够理解的吧QAQ
例题
P3834 【模板】可持久化线段树 2
算是模板题吧。对于这种多个询问并且询问满足单调性(第 k 小)的题目,就很适合整体二分。(其实带修也能做。具体来说,就是我们把原数列每一个位置当作一次修改,后面的就是查询。处理一个询问的时候,我们想要得出一个区间的第 k 小值与当前 mid 的关系,最常见的方法就是查询当前区间小于等于 mid 的数的个数,与 k 比一下大小。具体可以用树状数组实现。
#include
#include
#include
#include
#include
#include
算是讲完了吧QAQ
以后如果有时间会讲的更详细,也会放一些例题。现在就先咕咕咕了。
这篇随笔更多的是自己的学习体会,自己的学习笔记,可能写的不是很好,也不要介意。