Solution CF2061 C~E

Solution CF2061C Kevin and Puzzle

大炮打蚊子做法。

首先能写出一个简单的平方 dp:记 \(f_{i,j,0/1}\) 表示前 \(i\) 个人有 \(j\) 个说真话,第 \(i\) 个是否说真话的方案数。则有:

\[\begin{align*} f_{i,j,0}&=f_{i-1,j,1} \\ f_{i,j,1}&=\begin{cases} f_{i-1,j-1,0}+f_{i-1,j-1,1} & i-j=a_i\\ 0 & otherwise. \end{cases} \end{align*} \]

发现形式为交换两个数组,然后将其中一个全部赋值为 \(0\) 再对其中某一个单独操作。

交换数组可以通过滚动代替掉,赋值为 \(0\) 直接使用线段树维护数组并且打标记即可。

时间复杂度 \(O(n\log n)\)

Solution CF2061D Kevin and Numbers

妙妙题。

第一眼看这个似乎不太好做,因为每次选择合并哪两个会对后面产生影响。

但是我们发现 \(|x-y|=1\) 有一个特殊的性质,就是确定了合并后的 \(x+y\) 就能倒退出唯一的 \(x,y\)

利用这个性质,考虑倒着变成每次选择 \(b\) 中一个数分裂成两个。

大力 STL 维护,每次找 \(b\) 中最大的数,如果其出现数量比 \(a\) 中的出现数量小无解,因为已经是最大的数了。遇到多余的 \(1\) 无法分解和匹配时也是无解。

时间复杂度 \(O(n\log n)\)

Solution CF2061E Kevin and And

也是妙妙题,但是因为【】调了好久。

考虑 \(m\) 很小能带来什么:由于多个操作作用到一个值上并不好处理,考虑枚举所有 \(2^m\) 种可能的操作,算出 \(w_{i,j}\) 代表对于 \(a_i\) 进行 \(j\) 次操作能从和上减去多少。这个需要稍微精细实现一下做到 \(O(n2^m)\) 而不是 \(O(nm2^m)\)

直接做还是不太好处理,考虑对 \(w_i\) 差分一下,变成了多进行一次操作产生的额外贡献。

发现差分出来的 \(w_i\) 一定单调不增,因为新操作一次能产生的贡献越来越小。直接对差分出来的所有数排序取前 \(k\) 大,则选中了 \(i\)\(j\) 操作,所有小于 \(j\) 的操作已经被选择过了。

时间复杂度 \(O(n2^m+nm\log(nm))\)

posted @ 2025-03-20 18:35  UniGravity_qwq  阅读(7)  评论(0)    收藏  举报