补题日志
补题日志
Codeforces rating:1770
- goal:1900
ATcoder rating:1254
- goal:1600
Codeforces Round 915 (Div. 2)
D
不难发现,设当前排列为 \(q_1,q_2\dots q_n\) ,把 \(q_1\) 移到末尾,造成的影响有:
- 对于前缀中 \(\text{mex}_i<q_1\) 的 \(i\) ,移动后不改变它的值。
- 对于前缀中 \(\text{mex}_i>q_1\) 的 \(i\) ,移动后 \(\text{mex}_i=q_1\) 。
- 前缀中不可能存在 \(\text{mex}=q_1\) 的 \(i\)。
- 修改完之后在末尾添加一个 \(n\) 即可。
这样可以用树状数组直接维护每个前缀 \(\text{mex}\) 的出现次数,修改时统计次数+推平即可。
或者采用单调栈维护每个值的出现次数,修改时把大于当前值的暴力合并。
因为段数最多出现 \(n+n\) 次,所以是 \(O(n)\) 的。
E
叶子数(区间长度)相同,线段树的形态一定相同,可以从这一点出发考虑 DP。
设 \(f_i\) 表示有 \(i\) 个叶子的树的答案,考虑左右儿子的答案合并。
不难发现,左右子树的根节点编号由 \(1\) 变为了 \(2,3\) ,只需要考虑它们的变化,再统计根节点的贡献即可。
如果只考虑往左儿子走,那么不难看出答案就是儿子答案的两倍。
而往 \(u\) 的右儿子走,权值则变为 \(2u+1\) ,可以看作根节点编号为 \(2u\) 和 \(1\) 两种情况下的权值合并。
- \(2u\) 部分即儿子答案的两倍,再统计左儿子时已经考虑。
- \(1\) 部分则为当前子树的 \(f\) 值,即 \(f_i\) (设其叶子数为 \(i\) )。其该部分贡献不随后续 \(\times 2\) 而发生改变。
故可以记录 \(g_u\) 表示有 \(u\) 个叶子的树中所有右儿子 \(1\) 部分贡献和,转移时加上右儿子的 \(f\) 值:
\[g_u=g_{\frac u 2}+g_{\frac{u+1}2}+f_{\frac u 2}
\]
最后统计根节点贡献,只需要把左右子树中叶子的集合数乘起来,注意两边都非空即可。(不能只在一个子树选)
\[f_u=2f_{\frac u 2}+2f_{\frac{u+1}2}+(2^{\frac u 2}-1)\times(2^{\frac{u+1}2}-1)
\]