补题日志

补题日志

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) \]

posted @ 2023-12-21 23:37  Alansp  阅读(12)  评论(0编辑  收藏  举报