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.