Atcoder ABC403 题解
ABC403
A
判一下下标如果为奇数就加,为偶数就啥也不做。
B
串长很小,可以直接枚举 \(T\) 的每个下标 \(i\),看看以 \(i\) 开头,长度为 \(\text{size}(U)\) 的子串是否与 \(U\) 相等。
这里相等定义为:除 ? 之外,其他字符都相等。
这里封装了一个函数,看起来比较优雅。
C
弄一个 set<pair<int, int> >,记录每一条 \(1\) 操作的信息。
再弄一个数组,表示 \(i\) 是不是允许访问所有网页。
对于每个询问,只需回答 set 中是不是有 \((x, y)\),及 \(x\) 是不是有所有网页。
D
发现一堆堆差为 \(D\) 的数,构成一堆链状结构。
弄一个桶记录一下每种数出现次数。
我们对每条链进行 DP,考察这条链最多能选几个数,如果 \(i\) 这种数选,那么最优从 \(i-2D\) 转移来。如果 \(i\) 这种数不选,那么最优从 \(i-D\) 转移来。
最终最多能选的数的个数就是链末端元素的 DP 值之和。
别忘了特判 \(D=0\)。
E
有关前缀,不难想到字典树,属于是字典树上维护一些信息的套路题吧。
建出一颗 Trie,初始为空。
对于操作 \(1\),我们就正常插入到 Trie 中。它对应的末节点 \(p\),如果 \(p\) 有子树,那么子树中所有 \(Y\) 集合中的串都含有该字符串作为前缀,要将贡献去除。
对于操作 \(2\),我们插入到 Trie 中时,如果途径了 \(X\) 中字符串的一个末尾结点,那么这个字符串已经包含了一个非法前缀,return 掉就行。否则,\(Y\) 中又多了一个合法字符串,答案加一。
那么,如何去除操作 \(1\) 的贡献呢?
以给定字符串(末结点为 \(p\))作为前缀的字符串,一定在 \(p\) 的子树中。我们只需要将一个 \(Y\) 中字符串的贡献挂在结点上,再将其做子树和,维护这个子树和即可。
每次修改单点贡献,或去除贡献,会影响末结点到根的路径,暴力修改其中每个结点的信息就行,时间复杂度 \(O(s_i)\)。
注意,每次 \(1\) 操作之后要砍掉 \(p\) 下子树,否则会导致一个 \(Y\) 中字符串被两个前缀去除贡献,时间复杂度 \(O(C)\)。
一次插入是 \(O(s_i+C)\) 的,总复杂度 \(O(\sum s_i + nC)\),其中 \(C\) 为字符集大小。
F
DP,加方案输出。
记 \(f_i\) 为结果为 \(i\),最后一次运算为 + 的最短表达式长度,\(g_i\) 为最后一次运算为 *。
转移很好想,\(f\) 的转移只需枚举加数,此时加数外没必要套括号;\(g\) 的转移只需枚举乘数,但这时注意,如果某个加数的最后一次运算为 +,也即从 \(f\) 转移,要在外面套上括号(长度加 \(2\))。
输出方案,只需用两个辅助数组,记录 \(f_i\) 的转移来源,输出时对应好,递归输出就行。
时间复杂度 \(O(n^2)\)。
submission.
G
看起来很唐的一道题,但是没时间胡了。
花里胡哨讲一通,实际上就是强制在线。
弄一个动态开点权值线段树,每个结点记录区间的奇数排名和、偶数排名和,和一个翻转 tag。
不难发现,加入一个数会使大于它的排名奇偶性发生颠倒。
于是只需维护两个操作:
- 定权值个数加一,同时将大于这个数的 reverse tag 弄一弄。
- 全局奇数和,注意 tag 的下放与影响。
时间复杂度 \(O(Q \log V)\),其中 \(V\) 为值域。

浙公网安备 33010602011771号