LOJ2461 完美的队列 分块

传送门


如果对于每一个操作(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(Msqrt{N}))的。

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

代码

原文地址:https://www.cnblogs.com/Itst/p/11172874.html