Educational Codeforces Round 82
A. Erasing Zero
Solution
删去第一个 $1$ 和最后一个 $1$ 之间的 $0$.
Code
1 |
|
B. National Project
Solution
找到达到要求的 “good day” 在第几块(一个连续 $g$ 天算一“块”),计算此时够不够 $n$ 天。
Code
1 |
|
C. Perfect Keyboard
Solution
检查字母是否形成一条链,特判一个字母的情况。
Code
1 |
|
D. Fill The Bag
Solution
显然 $n>\sum a_i$ 时无解,否则一定有解。
设 $bn$ 是 $n$ 的二进制表示,$bt$ 每一位是对应 $a_i$ 的出现次数,那么题述操作可转化为:
- $bt$ 低位 $2$ 变高位 $1$,花费 $0$. 例如:$105020\rightarrow121100$
- $bt$ 高位 $1$ 拆成低位 $2$,花费 $1$. 例如:$101000\rightarrow100200$
从低到高依次考虑 $bn$ 中的 $1$,先尝试用 $bt$ 的低位合成高位消去它(花费 $0$),不行的话就用 $bt$ 的高位拆成低位消去它(花费 $=$ 高位与低位的差)。
Code
1 |
|
E. Erase Subsequences
Solution
【参考官方题解】$t$ 是由两部分拼成的,自然可以想到枚举拼接点,把 $t$ 拆成 $a,b$ 两块。问题转化成:已知 $a,b$,判断 $s$ 能否通过题目操作生成 $a,b$.
考虑 $dp$:
- $dp$ 状态:设 $dp[i][j]$ 表示能生成 $a$ 的前 $i$ 位和 $b$ 的前 $j$ 位的 $s$ 中最小位置。
- 转移方程:设 $k=dp[i-1][j]$,则我们已经知道 $a$ 的前 $i-1$ 位和 $b$ 的前 $j$ 位至少需要从 $s_{1…k}$ 生成出来,现在在 $t$ 后面加上 $a_i$,则 $s$ 中的最小位置就是 $k$ 之后第一个出现 $a_i$ 的位置。为此,我们预处理一个 $nxt[pos][ch]$,用来表示 $s$ 中 $pos$ 位置之后第一个 $ch$ 的位置。于是乎,$dp[i][j] = nxt[k][a_i]$;同理,设 $l = dp[i][j-1]$,有 $dp[i][j]=nxt[l][b_j]$,二者取最小即可。
- 转移顺序:由方程可知,循环 $i,j$ 即可。
- 边界条件:$dp[0][0] = 0$
Code
1 |
|
F. Number of Components
Solution
【参考官方题解】我们单独考虑每个颜色。由于 $c_i\leq c_{i+1}$,所以对于每个颜色来说,一定是先加再删,不会在删之后有加入的情况。加的过程用并查集维护当前时间与上一时间的连通块改变量;删的过程是一个经典的删边并查集,即倒序加入,维护的倒序改变量即正序的负的改变量。
Tricks:为编程方便,我们可以增加在 $q+1$ 时间处删掉所有颜色的操作;然后并查集维护改变量,也就是说答案数组是一个差分数组。
Code
1 |
|
G. Sum of Prefix Sums
Solution
【参考官方题解】树上路径问题,考虑点分治。
先思考一个简化版本:求 $s_1+s_2+\cdots+s_k$ 的最大值。那么我们在计算经过重心的路径时,只需要统计来自不同子树的权值最大路径即可,而且这些路径的一端一定是叶节点。
现在观察要求的式子:
其值与路径长度挂钩,我们只好无奈地对于每个叶节点都去考虑其他子树中的叶节点对它的答案。一对一考虑是 $O(n^2)$ 的,需要对上式进行一些调整:设分治点为 $c$,它的一个子树 $A$ 有叶节点 $x$,另一个子树 $B$ 有叶节点 $y$,从 $x$ 到 $c$ 的路径上的数字是 $a_1,a_2,\cdots,a_k$(包括 $c$),从 $c$ 到 $y$ 路径上的数字是 $b_1,b_2,\cdots,b_l$(不包括 $c$)。 设 $sum_A=\sum\limits_{i=1}^ka_i$,$psum_A=\sum\limits_{i=1}^k(k-i+1)a_i$,$psum_B=\sum\limits_{i=1}^l(l-i+1)b_i$,那么原式可写作:
上文提到,我们要枚举每个叶节点,计算它与其他子树的叶节点的答案。假设我们正在枚举一个叶节点 $y$,也就固定了 $l$ 和 $psum_B$,视 $sum_A$ 为斜率,$psum_A$ 为截距,那么上式是一条直线在 $x=l$ 处的值加上 $psum_B$. 要求所有这些直线在 $x=l$ 处的最大值,就是一个李超线段树的模板了。
枚举按照一下顺序:正着扫一遍子树,每扫到一个子树先在李超树中询问,然后将其加入李超树,然后再反过来扫一遍(因为路径答案与方向有关)。
注意:
- 特判只有一个子树的情况
- 清空李超树时用一个回收队列记录,不要直接全部清空(破坏复杂度)
Code
1 |
|
Educational Codeforces Round 82
http://xyfjason.github.io/blog-xcpc/2020/02/13/Educational-Codeforces-Round-82/