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\) 个位置的最大贡献,转移为:
复杂度 \(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\) 个儿子,有转移:
使用树哈希或者括号序用来判断形态相同的儿子子树,复杂度 \(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 同理,变成 B 和 1。
下文中的 \(S,T\) 均为完成上述操作后的 \(S,T\)。原题就变成了,交换 \(S\) 中相邻的 0A,1B,AB 后使 \(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)\)。

                
            
        
浙公网安备 33010602011771号