Codeforces Round 854 补题总结

发布时间 2023-04-29 16:06:20作者: -zyc-

Codeforces Round 854 补题总结

前言

昨天做这套题很不顺,今天补完题大概总结一下。

总结

Recent Actions

按题意模拟即可,考虑到前 \(n\) 个数一定始终在后 \(m\) 个数的前面,所以说当当前队列中如果没有出现 \(x\) 而在第 \(i\) 轮放进了 \(x\),那么当前在队首的编号小于 \(n\) 的数被淘汰。

Equalize by Divide

首先可以证明如果有数列中有 \(1\) 且不是全为 \(1\) 那么一定无解,并且其它情况一定有解,证明如下。

引理一:

如果有两个数 \(x,y\),那么这两个数不断令大的数除以小的数,最终一定会有一个数变为 \(2\) 或者两个数变成相等。因为最终一定会出现 \(y\le x < 2y\)

引理二:

如果序列中出现 \(a_i=2\),那么令其他 \(a_j\not=2\) 不断 \(a_j\gets \lceil \dfrac{a_j}{a_i}\rceil\),最终一定全都相等。

这个比较显然就不证明了。

所以综上所述,不断令数列中的最大值除以最小值,直到所有数都相等或出现 \(2\) 然后按引理二构造即可。

Double Lexicographically Minimum

这题样例还是比较强的。

首先肯定从 \(a\) 开始考虑每种字符的位置,容易想到如果第 \(i\) 种字符个数为偶数就直接两边对称放即可,下面说一下如果我们枚举到一个奇数怎么办。

枚举到奇数可以先把他按照偶数的方式放置到只剩 \(1\) 个,然后再考虑这最后一个怎么放,其实可以通过 \(\texttt{bbcca}\)\(\texttt{bbab}\) 这两个样例归纳出两种情况:

  1. \(\texttt{a}\) 放到其中一边,然后从另一边开始贪心的从小到大枚举,如 \(\texttt{bbcca}\)
  2. 将另一种字符先按照偶数的方式放置,然后在最中间将 \(\texttt{a}\) 放置,如 \(\texttt{bbab}\)

那么什么时候用按照 1 来构造,什么时候按 2 构造呢?手玩可以发现,如果目前剩余的字符种类多余两种应该按 1 构造,否则如果剩余两种字符按 2 构造,如果剩一种字符直接用当前字符把剩余位置填满即可。到此构造完毕。

Hot Start Up (hard version)

这里就不放 easy version 了。

比较好想到一个 DP 转移:令 \(dp_{i,j,k}\) 表示考虑到第 \(i\) 个程序,第一个 CPU 运行第 \(j\) 种程序,第二个 CPU 运行第 \(k\) 种程序的最小时间,这样是 \(O(n^3)\) 转移,考虑优化。

因为执行到第 \(i\) 个程序一定有一个 CPU 上是第 \(a_i\) 中程序,所以状态数可以减少,变为 \(dp_{i,j}\) 表示考虑到第 \(i\) 个程序,除了 CPU 上是 \(a_i\) 的那个 CPU 上的是第 \(j\) 种程序的最小时间,转移如下:

\[\begin{cases} dp_{i,j}&=dp_{i-1,j}+cost(a_{i-1},a_i)\\ dp_{i,a_{i-1}}&=\min_{j=0}^{k}dp_{i-1,j}+cost(j,a_i) \end{cases}\ \ \ \ \ \ \ \ cost(x,y)=\begin{cases} cold_y,&x\not=y\\ hot_y,&x=y \end{cases} \]

这样是 \(O(n^2)\) 的,进一步可以用线段树优化,维护区间最小值,支持区间加,单点修改,复杂度 \(O(n\log n)\)

City Union

这道题要求的条件的充要条件是最终的联通块每一行每一列拆开来看仍然是一个连通块,所以可以先把不符合要求的行和列补好,然后看是否联通,如果仍然不连通,就按如下处理(以两个块位置关系为左上、右下为例子):

.##...
##....
#.....
.....#
....##
...##.

如上图,可以先把左上角的连通块的右下方部分补成直角,直角顶点记为 \(P\),再把右下方连通块的左上部分补成直角,顶点为 \(Q\),然后将 \(P,Q\) 按最短路径连接即可,过程如下(\(O,X\) 为补的部分):

.##...                                .##... 
##O...                                ##O...
#OP...                                #OPX..
...QO#                  -------->     ...QO#             
...##.                                ...##.
...##.                                ...##.

然后就是一个模拟了。

Halve or Subtract

定义对每个数三种操作:

  1. 只进行题目中的第一种操作
  2. 只进行题目中的第二种操作
  3. 先进行题目中的第一种操作,再进行第二种操作。

由于如果每个数都只进行 1,2 操作可以直接可悔贪心,所以着重处理进行 3 操作。

引理1:

3 操作的对象一定是从大到小排序后的前缀

证明:

对于两个数 \(x,y(x>y)\),一定有

\[x-\lceil\dfrac{x}{2}\rceil \ge y-\lceil \dfrac{y}{2}\rceil\\ \min(b,\lceil\dfrac{x}{2}\rceil)\ge \min(b,\lceil \dfrac{y}{2}\rceil) \]

所以说两式相加有 \(LHS\ge RHS\),也就是对 \(x\) 进行 3 操作带来的价值更大。

所以枚举那些数进行 3 操作即可(一定是一个前缀),复杂度 \(O(n^2\log n)​\)

Count Voting

本题限制条件太多,感觉顾头不顾尾,其实可以考虑去掉某个限制条件最后把多于方案去掉即可。

可以把一个人收到 \(c_i\) 票拆成 \(c_i\) 个人每个人都收入一票,这让投票得票全是 \(1\) 比较好处理,最后将答案乘 \(\prod \dfrac{1}{c_i!}\) 即可(因为一个人的 \(c_i\) 张票之间无序)。

然后 DP 就比较显然了。\(dp_{i,j}\) 表示前 \(i\) 个组内相互投票,已经投出 \(j\) 张票的方案数,转移的话枚举第 \(i\) 个组内给前 \(i-1\) 个组投了 \(p\) 张票、第 \(i\) 个组收获 \(q\) 张票即可。

\(a_i\) 表示第 \(i\) 个组内的人数,\(b_i\) 表示第 \(i\) 个组内的人的得票之和,\(sum_a,sum_b\) 为前缀和,则有:

\[dp_{i,j+p+q}=dp_{i-1,j}\times \binom{a_i}{p}\times \binom{{sum_b}_{i-1}-j}{p}\times p!\times \binom{b_i}{q}\times \binom{{sum_a}_{i-1}-j}{q}\times q! \]

复杂度 \(O(n^3)\)