LOJ2461 完美的队列 分块

匿名 (未验证) 提交于 2019-12-02 23:47:01

传送门


如果对于每一个操作\(i\)找到这个操作中所有的数都被pop掉的时间\(ed_i\),那么剩下就直接差分覆盖一下就可以了。

那么考虑如何求出\(ed_i\)。发现似乎并没有什么数据结构能够维护于是考虑分块。

对于每一个块分别考虑整块操作和散块操作的答案。

先考虑整块:注意到对于按照时间顺序的整块操作,答案一定是递增的,所以考虑双指针优化。

假设当前做到第\(j\)个操作,维护指针\(k\)表示当前已经做完了\((j,k]\)的所有操作。我们需要考虑当前操作会对当前块中的每一个queue产生怎样的影响。

记录\(B_i\)表示每一个队列还有\(B_i\)次会把当前数pop掉并记录下\(Mx\)表示\(B_i\)的最大值,同时记录标记\(cov\)表示\(B_i\)的区间标记。每一次\(k\)右移的时候,如果当前操作是整块操作就\(cov+=1\),否则将当前区域的所有\(B_i -= 1\)然后更新\(Mx\),当\(Mx \leq cov\)时表示当前操作的所有数全部被pop掉了。\(j\)往右移的时候就是撤销操作。

然后考虑散块。因为散块的数量是\(O(M)\)的,所以我们可以暴力枚举块中的每一个位置,复杂度也就是\(O(M\sqrt{N})\)的。

也就是说在每一次做的时候我们只能枚举所有散块操作。考虑处理出所有的散块操作,并处理出所有的散块操作之前的所有整块操作,为了方便可以在所有的操作之后加上一个空的散块操作。注意到散块操作和整块操作一样,被pop的时间更晚的加入的时间也会更晚,所以也可以双指针优化。利用跟上面类似的操作即可计算出结果。

代码

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!