浅谈整体二分

发布时间 2023-03-28 20:15:34作者: Xun_Xiaoyao

有的时候通过二分答案可以很容易的得到答案,所以我们考虑将所有的操作和询问离线下来,对整体进行二分,从而实现问题的求解。
在处理问题时,一个操作或询问一般只会对二分的左半边或者右半边中的一个做贡献,所以单层的操作数是线性的,全局的操作数是线性对数的,保证的询问的复杂度。

[国家集训队]矩阵乘法

给定一个 \(n\times n\) 的矩阵,\(Q\) 次询问,每次求一个子矩阵中的第 \(k\) 小数。
考虑整体二分,对于所有在 \([l,r]\) 之间的数,每一个 \([l,mid]\) 中的数作 \(1\) 个贡献,然后对于每一个答案在这个区间内的数,查询子区间贡献和 \(sum\)
如果 \(sum\geqslant k\),说明第 \(k\) 大在 \([l,mid]\) 中,将这个询问下放到 \([l,mid]\)
否则,说明第 \(k\) 大在 \([mid+1,r]\) 中,**将 \(k\) 更新为 \(k-rem\) **,并将询问下放到 \([mid+1,r]\)

复杂度分析,单层使用二维树状数组维护,单层复杂度为 \(O((n+Q)\log^2n)\),总体复杂度为 \(O((n+Q)\log^n\log a)\)

[ZJOI2013]K大数查询

维护 \(n\)可重集,支持两种操作:

  • \([l,r]\) 的集合中加入 \(c\)
  • 查询 \([l,r]\) 所有集合的并中的第 \(k\) 大数。

将所有答案在 \([l,r]\) 内以及在插入的数在 \([l,r]\) 间的所有操作按顺序维护。
使用树状数组维护一次函数实现前缀加和前缀求和,按顺序执行所有的加入数在 \([l,mid]\) 的操作一和所有询问二。
如果对于某个询问到的值 \(sum\),如果 \(sum\geqslant k\) 则答案在 \([l,mid]\),否则答案在 \([mid+1,r]\),使用与上一题类似的方式下放即可。

总体复杂度为 \(O(Q\log n\log c)\)