AtCoder ARC194 题解

AtCoder ARC194 题解

前言

前四题时自己通过的,最后一题题解写得很清楚,就很快通过了。

A - Operations on a Stack

发现如果操作序列是 add-add-del-del 那么可以转化为 add-del-add-del,它们的贡献是一样的。

即我们现在有两种操作:选择 \(a_i\);跳过 \(a_i,a_{i+1}\),贡献为 \(0\)。那么设 \(f_i\) 表示考虑完前 \(i\) 个位置的最大贡献,转移为:

\[f_i+a_{i+1}\to f_{i+1} \]

\[f_i\to f_{i+2} \]

复杂度 \(O(n)\)

B - Minimum Cost Sort

考虑到由于代价与位置有关,那么我们有一种贪心的策略「先尽量在前面交换,之后再在后面交换」,然后我就想到一种策略:

从前往后扫一遍,前面扫过的所有数已经排好序了,然后将当前扫到的数不断交换插入其中使得有序。

那么用一个树状数组维护比它大的个数即可,交上去发现它过了。这里没开 long long 罚了一发。

复杂度 \(O(n\log n)\),证明未知。

C - Cost to Flip

首先对于 \(0\to 0\) 的不用管。而对于 \(0\to 1\)\(1\to 0\) 可以想到排序后先做 \(1\to 0\),再做 \(0\to 1\),这样是最优的。证明考虑一对先做 \(0\to 1\),再做 \(1\to 0\),交换它们一定更优。

而发现还有一种情况,即 \(1\to 1\),我们可以在开始 \(1\to 0\),再在结尾 \(0\to 1\),这转化成了上述两种情况。我们可以选择一些 \(1\to 1\) 执行这个策略,并且我们发现一定是从大往小执行这个策略。

那么我们用树状数组维护两个序列,分别是 \(0\to 1\)\(1\to 0\),需要维护后缀值域个数以及前缀值域和。枚举执行 \(1\to 1\) 策略的前缀,往树状数组里插入和查询即可实时维护答案。

复杂度 \(O(n\log n)\)

D - Reverse Brackets

首先考虑把括号序变成树状结构,排序以后二分加递归即可。

由于每一括号序都唯一对应一棵树,那么答案就是对每个节点可以重排儿子,问有多少种树的形态。

\(f_i\) 表示以 \(i\) 为子树的树形态个数。那么设与儿子 \(j\) 形态相同的儿子子树共 \(cnt\) 种,当前已经考虑完了 \(c\) 个儿子,有转移:

\[f_i\gets f_i\times f_j^{cnt}\times \binom {c+cnt} {cnt} \]

使用树哈希或者括号序用来判断形态相同的儿子子树,复杂度 \(O(n\log n)\)\(O(n^2\log n)\)

代码用树哈希被卡了,用 string 存括号序就过了。

E - Swap 0^X and 1^Y

题解做法:先判掉 01 个数不等。考虑把连续的 \(c\)0 变成 \(\lfloor \frac c X\rfloor\)A\(c\bmod X\)0。对于 1 同理,变成 B1

下文中的 \(S,T\) 均为完成上述操作后的 \(S,T\)。原题就变成了,交换 \(S\) 中相邻的 0A1BAB 后使 \(S\) 变为 \(T\)

考虑将 \(S\)\(T\) 经过下列操作直到不能操作,变成 \(S'\)\(T'\)

  • 子串 A0 交换。
  • 子串 1B 交换。
  • 子串 AB 交换。

如果 \(S'=T'\)\(S\) 可变为 \(T\)。那么现在考虑 \(S'=T'\) 的充要。

只要考虑如下三个序列:01 构成的子序列,所有相邻 1 之间 A 的个数,所有相邻 0 之间 B 的个数。

如果 \(S,T\) 的上述三个序列都相等,则 \(S'=T'\)

证明首先考虑 01 的子序列是不能交换的,然后 1 之间的 A 全部只能放在 1 之前,0 之间的 B 全部只能放在 0 之后。

时间复杂度 \(O(n)\)

posted @ 2025-03-11 22:12  dengchengyu  阅读(135)  评论(0)    收藏  举报