7月CF杂题

怎么七月了?六月的只写了一道题捏。

Educational Codeforces Round 151 (Rated for Div. 2)

俺寻思能行。

D. Rating System

为什么大家都切那么快捏。

显然 \(k\) 一定是 \(a\) 数组的一个前缀和。假设 \(k=\sum\limits_{i=1}^x a_i\),剩下的等价于处理初值为 0 且 \(k=0\) 的子问题。我们需要在 \(O(1)\) 的时间内解决。

先考虑能不能 \(O(n)\)。你枚举它最后一个会把它提到 0 的位置,后面的就是后缀和,所以后面那坨的答案就是 \(\max\limits_{j=x}^n\left\{\sum\limits_{k=j+1}^n a_k \right\}\)。维护后缀和最大值就是 \(O(1)\) 了。

它为什么是对的?首先 rating 在任意时刻都不会小于 0,所以当当前 rating 为 0 时它就是对的;当 rating 大于 0 时,答案会被算小,但这证明我们可以往前找到第一个 rating 等于 0 的位置,且从那到这一段中的变化量为正,在那个点我们就可以得到这个正确答案。

E. Boxes and Balls

这是一个 \(O(n^3)\) 的做法。但它常数极小,加上火车头可以跑进 0.8 秒。

容易发现在最后得到的序列中从左往右第 \(i\) 个 1,一定是初始序列中从左往右第 \(i\) 个 1,因为它只能相邻交换。所以,一种方案需要走的最少步数,就是对应 1 的位置之差的和。定义 \(f_{i,j,k}\) 表示前 \(i\) 个格子,有 \(j\) 个 1,总共需要走 \(k\) 步,有多少满足条件的序列,转移就是枚举当前位置放 0 还是 1。

容易发现对于那些没走满 \(k\) 步的方案,如果存在空位,那么你可以“左右横跳”来凑满 \(k\) 步。一次最少多走两步,所以多走的步数是 2 的倍数。记 1 的个数为 \(c\),最终答案就是 \(\sum\limits_{k'=0}^k[k'\equiv k\pmod 2]\cdot f_{n,c,k'}\)

第一维可以压掉,时间复杂度 \(O(n^3)\)。这样过不了,但是你发现 0 和 1 是等价的,所以上述定义改为 0 也是一样的,你可以选个数少的来 dp。实现再优秀一点就可以跑进 0.8 秒。


但是这显然不是出题人的意图,考虑再次优化。假设第 \(i\) 位的前缀和为 \(s_i\),那么这一位最终的前缀和 \(j\) 只可能取在 \([s_i−\sqrt{k},s_i+\sqrt{k}]\),因为不论是要把前 \(i\) 个数中的 \(\sqrt{k}\) 个 1 移出还是把后面的 \(\sqrt{k}\) 个 1 加入前 \(i\) 个数都至少需要 \(k\) 次操作。时间复杂度 \(O(nk\sqrt{k})\),实测只用了 0.1 秒。

posted @ 2023-07-02 10:58  xx019  阅读(8)  评论(0编辑  收藏  举报