💋💉💩💩味道 Round 4
[EGOI 2026] 披萨大师
给定一个 \(0 \sim n-1\) 的排列 \(a\) 和 \(m\) 个初始为空的栈,进行如下操作:
- 将前 \(m\) 个数按照顺序放到栈中。
- 从下一个数开始,找到一个栈顶 \(< a_i\) 且栈顶最大的栈,将 \(a_i\) 放入这个栈中;如果找不到,则不放入这个 \(a_i\)。
给定每个栈最终从底到顶的所有数 \(b_{i, j}\),构造一个字典序最小的合法的初始排列 \(a\)。
\(1 \le n,m \le 3 \cdot 10^5\)。
初始的 \(m\) 个数的位置是固定的,先全部放完。然后把栈从小到大排个序开始跑。首先观察性质,我们把这个栈放到值域上看。每次选择一个栈顶 \(< a_i\) 且栈顶最大的栈放入,不妨把栈顶记为 \(t_i\),相当于找到这个栈,将 \(t_j \gets a_i\),且不存在 \(t_j<t_k<a_i\)。所以 \(t_i\) 的相对顺序不会改变。
接下来看这道题就非常简单了,由于相对顺序不改变,所以每次如果能放前面的栈就放前面的栈。容易发现这是一个递归式的子问题,如果 \(t_1 < t_2 < b_{1, cur}\),那么就把第一个栈删掉,处理要使 $t_2 > $ 某个值并使字典序最小的问题。建出图结构,精细实现可以做到除排序外 \(\mathcal O(n+m)\)。
[PA2022] Płótno
给定一个 \(2 \times n\) 的循环网格,第 \(i\) 行第 \(j\) 列的网格记为 \((i, j)\)。每个网格上有一个独一无二的数字,定义两个网格相邻当且仅当满足如下条件之一:
- 列相同。
- 行相同且列编号相邻,注意:列 \(1\) 和 \(n\) 是相邻的。
网格集合 \(S\) 是一个连通块,当且仅当任意属于该集合的两个网格能够通过每次走相邻的网格,且不经过不属于该集合的网格互相到达。
对每个 \(i = 1, \dots, k\),求颜色区间 \([\ell, r] \subseteq [1,2n]\) 个数,把网格上写的数在 \([\ell, r]\) 区间的所有数标记后,标记形成的极大连通块数量为 \(i\)。
\(1 \le n \le 10^5, 1 \le k \le 10\)。所有网格的数字构成一个 \(1 \sim 2n\) 的排列。
如果有心的话会发现这个题与 Two Segments 非常像。考虑扫描线,扫 \(r\),对于每个 \(l\) 维护 \(f_r(l)\) 表示 \([l, r]\) 的极大连通块数量。
考虑加入 \(r\) 对 \([l, r-1]\) 的影响。先不考虑环,有如下几种情况:
-
周围没有标记点相邻,增加一个连通块。
-
有一个标记点相邻,连通块数量不变。用
@表示新加入的点,*表示原来的标记点。....*@..... ........... -
有两个标记点相邻,连通块数量 \(-1\)。
....*@*..... ............ -
有三个标记点相邻,连通块数量 \(-2\)。
....*@*.... .....*..... -
与两个标记点相邻,但这两个标记点已经在一个连通块内,此时连通块数量不变,但由于刚刚的错误统计,需要修正为 \(+1\)。
....*@..... ....**.....\(-1+1 = \pm 0\)。
-
与三个标记点相邻,但这三个标记点已经在一个连通块内。修正为 \(+2\)。
....*@*.... ....***....
不难观察到我们不需要讨论这么多情况的。
可以统计 L 型标记的个数 \(c_1\),和相邻点的个数 \(c_2\),容易发现变化就是 \(c_2-c_1+1\)。
对于环,还是分类讨论一下:
-
等价于刚刚两个相邻点的情况,不过在一个跨环的连通块内:
*****@****** ............或
*******@.... *......*****刚刚会统计为 \(0\) 个连通块,再加上 \(1\) 即可。
-
对于跨环的 L 型,可以将数组复制一份统计。
然后就考虑用线段树怎么维护。我们找到三个相邻点分别对应的数、L 型中最小的数,用区间加法可以实现。然后线段树中维护前 \(k\) 小就可以把以 \(r\) 为右端点的区间数量算出来。容易观察到刚刚跨环连通块的出现次数只有 \(\mathcal O(n)\) 次,最终单独统计一下就完了。总复杂度 \(\mathcal O(n k \log n)\)。

浙公网安备 33010602011771号