做题记录 2

[ICPC 2023 Nanjing R] 红黑树

先考虑一个暴力一点的 dp。设 \(f_{u,i}\) 表示 \(u\) 子树内,\(u\) 到每个叶子的路径上的黑点数量都为 $i 的最小更改次数。有转移:

  1. \(s_u=0\)

    \[f_{u,i}=\min \left\{\sum_{v\in son_u}f_{v,i},(\sum_{v\in son_u}f_{v,i-1}) +1\right\} \]

  2. \(s_u=1\)

    \[f_{u,i}=\min \left\{(\sum_{v\in son_u}f_{v,i})+1,\sum_{v\in son_u}f_{v,i-1}\right\} \]

考虑到叶子节点的 \(f\) 是一个下凸壳,而两个凸壳对位相加后还是凸壳,所以不妨考虑凸优化,同时把转移中的那些加 \(1\) 减 \(1\) 的系数也变成保证凸性的形式。

对于 \(s_u=0\) 的情况,其第二个转移可以视作是与一个由点 \(\left(0,0\right),\left(1,1\right)\) 构成的凸壳做 min+ 卷积。根据闵可夫斯基和,相当于在斜率序列中插入 \(1\) 并对整个斜率序列排序。对于 \(s_u=1\) 的情况,将 \(f\) 整体加 \(1\) 后分析可以同理得到是插入 \(-1\)。

接着考虑计算答案。相当于将维护的斜率中小于 \(0\) 的那些值加上,这个可以考虑在维护凸壳的过程中计算。

用小根堆维护斜率序列,现在的问题就是:

  1. 将两个堆对位相加

  2. 插入一个斜率

  3. 维护所有小于 \(0\) 的斜率的和

先考虑操作 \(1\)。考虑到凸壳对位相加后的点数是两者点数的最小值,所以直接类似于启发式合并就可以做到 \(\operatorname{O}(n\log^2n)\)。

然后考虑操作 \(3\),由于操作 \(1\) 我们是直接启发式合并暴力维护,所以这个可以在过程中记一个变量去一个个加。

然后就做完了,总时间复杂度 \(\operatorname{O}(n\log^2n)\)。

[CCPC 2024 重庆站] Median Replacement

看到中位数直接考虑枚举中位数 \(x\) 然后转成大于等于 \(x\) 为 \(1\) 小于 \(x\) 为 \(-1\),若和大于等于 \(0\) 则中位数大于等于 \(x\)。发现这个东西天然就是拆贡献的形式,所以考虑计算中位数大于等于 \(x\) 的数列数量。

稍微思考一下会发现一个非常基本的操作:如果连续 \(3\) 个数中有至少两个为 \(1\),那么另外一个数也可以变成 \(1\)。继续根据这个操作可以发现这样一定可以把所有位置都变成 \(1\)。

考虑如果任意两个 \(1\) 的距离都大于 \(2\),那么此时无论怎么操作一定是把一些 \(1\) 变成了 \(-1\),无法全部变成 \(1\)。因此,存在距离小于等于 \(2\) 的两个为 \(1\) 的位置是序列合法的充要条件。

枚举 \(x\) 做 dp。记录上一个 \(1\) 的距离(为 \(0,1,2\) 还是更大)和是否存在过距离小于等于 \(2\) 的两个 \(1\),分类讨论和 \(x\) 的大小关系然后转移即可。具体来说,所有区间被分成了 \(r_i<x\),\(l_i\le x\le r_i\),\(x\le l_i\) 三类,每一类的系数都是好算的。

发现这个对区间的分类在很多 \(x\) 都是一样的。因此考虑将与每个区间的大小关系都相同的那些数放在一起考虑(显然这些数是连续的)。发现对于第一种和第三种区间,转移是乘上一个常数。对于第二种,是乘上 \(x-l_i\) 或 \(r_i+1-x\)。因此直接把 \(x\) 当作占位符,最后的答案可以写成 \(\sum_{i=0}^{n}f_i x^i\) 形式。拉插快速求出区间对应的 \(\sum_{i=l}^r i^k\) 即可。

\(x\) 总共会被分成 \(\operatorname{O}(n)\) 段,拉插的每次复杂度是 \(\operatorname{O}(n)\),,把 \(x\) 当成占位符的 dp 可以做到单次 \(\operatorname{O}(n^2)\),所以总复杂度 \(\operatorname{O}(n^3)\)。

code

posted @ 2026-09-09 12:27  caoshurui  阅读(11)  评论(0)    收藏  举报