题目 | A | B | C | D | E |
---|---|---|---|---|---|
通过 | √ | ||||
补题 | √ | √ |
不应该随便打 Div. 1 的… 打了半个小时之后决定开始快乐补题。
A. Prefix Sum Primes
一个数列 \(a_i\in\{1,2\}\),令 \(S(n)=\sum_{i=1}^n a_i\),输出一个方案最大化 \(\sum_{p=1}^n [S(p)\text{ is a prime}]\)。
题解
如果只有一种数,那就只有一种放法。考虑存在 \(1,2\) 的情况,只要前缀和满足 \(\{2,3,\dots\}\),接着的位置只需要贪心地先放完 \(2\),再往后面补充 \(1\) 即可。
代码
1 |
|
B. Three Religions
三个串 \(a,b,c\) 和模板串 \(s\),每次操作可以向某个串后面添加一个字符或删掉一个字符,求经过 \(q\) 次操作之后,\(s\) 中是否有 \(a,b,c\) 的不相交子串。保证任意时刻 \(|a|,|b|,|c|\leq 250\)。
题解
首先有个东西叫做序列自动机,可以查询从第 \(i\) 个字符开始,字符 \(c\) 第一次出现的位置。(看起来很高端其实很简单)
考虑 \(f(i,j,k)\) 为匹配完 \(a,b,c\) 串的第 \(i,j,k\) 个字符后,最短匹配到了 \(s\) 的什么位置,则 \(f(i,j,k)\) 在 \(|s|\) 内说明答案存在。(DP 的具体转移方程见 Editorial)这个过程用序列自动机加速可以 \(\mathcal{O}(|a|^3)\) 处理完毕。
考虑修改,假设往 \(a\) 串加了一位,则每次需要新计算 \(f(i+1,j,k)\),这需要 \(\mathcal{O}(|a|^2)\) 的时间;考虑往 \(a\) 删除一位,则 \(f(i-1,j,k)\) 是已经计算好的,不需要重新计算。
注意 DP 过程可能会越界。总时间复杂度 \(\mathcal{O}(q|a|^2)\)。
代码
1 |
|
C. Tree Generator™
一个代表树的括号序列 \(s\),多次交换 \(s_i,s_j\)(保证交换之后是合法的序列),求每次操作后的直径。
题解
这道题有点神…
对于两个点,有 \(\mathrm{dist}(u,v)=\mathrm{dep}(u) + \mathrm{dep}(v)-2\times \mathrm{dep}(\mathrm{LCA}(u,v))\)。而括号序列代表的是一个树的 DFS 序,假设序列中 \(u\leq v\),则有 \(u \leq \mathrm{LCA}(u,v) \leq v\),即 \(\mathrm{dist}(u,v)=\mathrm{dep}(u) + \mathrm{dep}(v)-2\times \min_{u\leq i\leq v} \mathrm{dep}(i)\)。
因此只需要维护满足 \(a\leq b\leq c\) 的三元组 \((a,b,c)\) 在上式值的最大值即可。然后要维护这个值,需要维护各种奇奇怪怪的组合… 总之都是为了能够实现区间加法(进而线段树维护)而进行的。
小小总结一下:
- 括号序列是一个 DFS 出入序列。
- \(\mathrm{dist}(u,v)=\mathrm{dep}(u) + \mathrm{dep}(v)-2\times \mathrm{dep}(\mathrm{LCA}(u,v))\)。这个思路说明,可以通过维护 DFS 序上的极值,实现不知道 LCA 的情况下的树上两点距离计算。
- 括号序列的一个子串,在去掉匹配括号后留下来的序列代表了一条连续路径(右括号:向上到达该节点,左括号:向下走到该节点)
代码
1 |
|