整体二分学习笔记
当对一个集合中的每个元素都要进行一样的二分答案时,常可以对整个集合进行分治答案,将属于答案 \([l,mid]\) 和 \([mid,r]\) 的 \(i\) 重新排列成为左右两块完整的,然后对左右两块分别递归处理。具体见例题。
【例】[POI2011]Meteors
对于单个元素,单调性显然。
实现分治函数 void solve(l,r,x,y)
表示在已经预先保证下标 \([x,y]\) 的答案 \(\in [l,r]\) 的情况下,将下标区间 \([x,y]\) 按答案 \(\in [l,mid]\) 和 \(\in [mid+1,r]\) 分成两类。主函数中只用调用 solve(1,q+1,1,n)
。(q+1是用来判无解的,不必在意)
我们可以让 \([l,mid]\) 的流星雨都下下来,来看一下现在有哪些是已经满足了的,把这些放在左边,就是说答案应该在 \([l,mid]\) 中的(\(<mid\)),而反之放到右边,因为答案 \(>mid\)。假如分界点是 \(w\),那么接着递归 solve(l,mid,x,w)
和 solve(mid+1,r,w+1,y)
;执行此操作前将 \([w+1,y]\) 的 \(p\) 减去这次已经统计到的(因为每次加的 \([l,mid]\) 而不是 \([1,mid]\))。直到 l==r
时,将 ans[x]...ans[y]
都设为 l
回溯。
注:本题需要一些卡常,比较有效的是
- 在
get()
中if(s>p[x])
可以直接返回s
了,因为继续加下去没任何意义 - 不要
memset
树状数组,而是“还原现场”,实测 85pts->100pts