求一个序列的第k大,显然可以采取二分解决,但当询问量较大时,我们无法承受每次询问都二分一遍的时间消耗,将询问离线,使用整体二分,每次验证mid对所有询问是大是小,然后把询问分到两侧区间去进行递归计算,也是利用了分治的思路
对于修改操作,我们根据其影响来确定是被划分到左侧区间还是右侧区间即可
一般利用线段树或树状数组来维护信息
我们把所有操作离线下来, 用solve(L,R,l,r)表示第[L,R]个操作对应的答案在[l,r]区间内,现在我们需要划分这些操作。修改操作:如果修改的值大于mid,显然会产生影响,我们在线段树上对其进行修改,把它们放到右侧区间内,如果小于等于mid,那么就放到左侧区间。询问操作,每次查询线段树上[q[i].l,q[i].r]的区间内大于mid的数量val,如果val>k,那么一位置答案要大于mid,放到右侧区间,反之放到左侧即可。当l==r的时候,给L-R的所有询问填上答案即可。
这里清空线段树用了一个del_tag的方式,其实再操作一次add-1也
整体二分+二维树状数组即可,每次验证mid的时候<=mid的值标上1即可
不要二分值域,因为答案肯定是数组内的值,所以二分坐标即可
整体二分+普通树状数组 比较裸 代码
P7424 [THUPC2017] 天天爱射击
给定n个木板的在x轴上的位置,以及每个木板能经受的了几次射击,还有m颗子弹的射击位置(沿y轴方向),问每次射击后共有几个木板坏了