【题解】集训队互测 2018 完美的队列

发布时间 2023-09-21 09:34:35作者: Qiuly

假设 \(n,m\) 同阶。

我们实际要做的是,对于一个 \(i\) 时间的 \(\mathbf{push}\) 操作 \(l,r,x\) 找到其被清空的时间 \(j\),这样在 \([i,j)\) 这一段 \(x\) 就是存在的。最后只要合并相同 \(x\) 的区间即可。

\(l,r,x\) 对应到线段树上的 \(O(\log n)\) 个节点上。这样就可以对每个节点分开考虑问题了。

在一个节点的问题上,可能的事件有三种:一次由祖先贡献的完全覆盖 / 一次由子树贡献的部分覆盖 / 一次自己本身的覆盖。而要干的事就是,对于每一次自己本身的覆盖,往后找到其被清空的时间。

在线段树上 DFS,同时用一棵以时间为下标的线段树,维护祖先覆盖的时间。到了当前节点,我们事实上可以暴力地处理后两种事件,并且总量是 \(O(n\log n)\) 的。

于是,只要对着后两种事件做双指针,用线段树维护点权(即最开始每个位置都是 \(a_i\),每次操作对应区间减)。第一种事件带来的影响,只需要用时间为下标的线段树计算出现次数。

时间复杂度 \(O(n\log^2 n)\)