[CF2021C] Adjust The Presentation 题解

C1

没有修改。
我们直接模拟人排队的过程。枚举 \(b\) 的每一个元素 \(b_i\),看看当前 \(a\) 数组的头部是不是和 \(b_i\) 相等,若是,将 \(a_i\) 移到某个位置;否则就 No。

问题来了,每次怎么移动 \(a_i\) 呢?
我们发现并不需要显式地移动,只需把用过的 \(a_i\) 丢到一个集合里,想用的时候拿出来就行,因为可以移到任意位置。
每次判 \(b_i\) 的时候多看一眼这个集合里面有没有 \(b_i\)。如果有,那 \(b_i\) 这个元素就合法。

进一步地,我们还不需要显式地弄出这个集合。我们发现,我们只关心 \(a\) 中每个元素被丢进集合的时间戳 \(dfn_i\)。记元素 \(v\)\(a\) 中出现的位置为 \(pos_v\),那么判 \(b_i\) 的时候只需要看看是否 \(i \ge dfn_{pos_{b_i}}\) 即可。
那么这个 \(dfn_i\) 等于多少呢?显然等于 \(b\) 中第一个出现 \(a_i\) 的位置。

于是就做完了,时间复杂度 \(O(n)\)

C2

现在带修了,我们考虑如何快速判断合不合法。
我们(通过归纳手玩)注意到合法等价于 \(dfn\) 是升序的。原因在于,若不升序,记 \(i < j\)\(dfn_i > dfn_j\)。在 \(dfn_j\) 这个时刻,我们需要 \(j\) 这个人出来放幻灯片,但是前面 \(i\) 这个人没有走,卡住了 \(j\),于是不合法。升序当然合法。
也就是说,我们只需要单点修改 \(dfn\),全局判断是否升序即可。

如何单点修改 \(dfn\)?
我们对每个 \(a\) 中的下标开个 set,记录在 \(b\) 中出现的位置。于是实时的 \(dfn\) 就是 set 中的最小值。
修改只需变更 set 中的元素。
每次对于 \((s,t)\),需修改 \(pos_{b_s}\)\(pos_t\)

如何判断升序?
讲一个 set 的做法。
升序(这里的升序并非严格,为处理方便将 \(dfn\) 中某些元素设为 \(\infty\))等价于差分数组的最小值大于等于 \(0\)。每次改 \(dfn_u\) 就是改 \(diff_u\)\(diff_{u+1}\),用 multiset 维护最小值即可。

做完了,时间复杂度 \(O((n+q)\log n)\)

submission.

posted @ 2025-02-24 23:11  Water_M  阅读(18)  评论(0)    收藏  举报