整体二分

来源:互联网 发布:淘宝女包2017新款上市 编辑:程序博客网 时间:2024/03/29 08:03
In Short : 对于所有询问二分答案。
Specific:
     一般的二分答案通过判定该答案与询问的关系来进行缩小答案区间最后找到答案。
     而整体二分在这个基础上扩展成在二分答案中可以求出多个询问的答案。
     从第k大入手。
void Solve(int l,int r,int a,int b) {
     ...
}
     以上函数为 a 到 b 的询问其答案区间在 l 到 r 内。
     如果想要获取最后的答案,就需要把这个答案区间划分的越来越细,最后变成一个点就可以得到答案。
     现在的 mid 是要判定的答案,假如说我们要求一个第k大,那就先假设 mid 是所有询问的答案。接着将给出的数列(要求第k大的辣个数列)扫一遍(当然要做成操作的形式,保证整体二分的复杂度),将小于 mid 的数加进树状数组里,然后再统计这些数对a 到 b 询问的影响(即为普通二分中的“这个区间里有多少个小于等于mid 的数”)并利用这个对所有询问进行答案区间的划分。
     统计完影响后该加的加,该划分的划分,最后记得把影响全数消除掉。
     最后归纳一下算法流程(针对于每一层):
  1. 如果当前答案区间为一个点,把 a 到 b 询问的答案都变成这个点。
  2. 取出中间点 mid。
  3. 把数值小于等于 mid 的修改扔到树状数组里,在这个过程中同时统计对询问的影响。
  4. 还原树状数组。
  5. 扫一遍 a 到 b 的询问,根据已累计的cur和要求的k的大小关系分到两个区间内。
  6. 递归求解。
     例题:1.[BZOJ]3110:K大数查询AC
                    此题在BZOJ上数据被丧心病狂的出题人加强过,所以要开long long
                    另外还写了区间修改区间查询的树状数组
              2.[POJ]2104:Kth-Number AC
                    此题有剧毒,TMD居然有负数你在逗我(╯‵□′)╯︵┻━┻
                    记得把数字也当成操作随着二分递归下去(这样才可以保证复杂度)
0 0