$\newcommand{le}{\leqslant}\newcommand{ge}{\geqslant}$

AtCoder Grand Contest 037 学习

考场状况

第一把 AtCoder, 把我校的省队大佬以及另外两个兄弟拉进来组了个车队。两个小老弟原定帮我解决ABC, 最后他们就做了AB, 省队大佬率先切掉E, 我切掉了CD.

没想到名次这么靠前,下回不组车队了。

A. Dividing a String

题意:把一个字符串拆分成最少数量的子串使得相邻两个子串不相等。

笔记:

车队考场做法

同字符的连续段一定按照 $1, 2, 1, 2, \ldots$ 的长度分组,如果不能这么分就吃掉下一种数的头一个,这样不会更劣。如果最后一个数不能分组,就把上一组并进上上组。

题解做法

发现 $1+4, 2+3, 3+2, 4+1$ 至多有两个不合法,因此每段长不超过 $4$, 直接 DP.

B. RGB Balls

题意:给一个长度为 $3n$ 的球序列,红绿蓝三色各 $n$ 个。给 $n$ 个人各分三色球各一个,使每个人拿到的球标号极差之和最小,求分法数。

笔记:

车队考场做法

记一下目前各有多少个 RGBRGGBBR, 从左到右扫描,遇到红球时按照 GB>G/B>$\varepsilon$ 的顺序结合,别的类似。方案数即每次选法数之积乘上 $n!$.

题解做法

把三色球的下标分别从小到大排序为 $r_1, r_2, \ldots, r_n$; $g_1, g_2, \ldots, g_n$; $b_1, b_2, \ldots, b_n$. 设 $m_i=\min\{r_i, g_i, b_i\}$, $M_i=\max\{r_i, g_i, b_i\}$. 设第 $i$ 个人持球最小标号为 $a_i$, 最大标号为 $c_i$.

一方面,把 $r_i, g_i, b_i$ 给第 $i$ 个人可以得到极差之和 $\sum_{i=1}^n(M_i-m_i)$.

另一方面,不妨设 $a_1 < a_2 < \cdots < a_n$, 因为有 $k$ 个人持前 $k$ 个红球、绿球、蓝球,所以 $a_k \le m_k$. 因此 $\sum_{i=1}^n a_i \le \sum_{i=1}^n m_i$, 同理可得 $\sum_{i=1}^n c_i \ge \sum_{i=1}^n M_i$, 因此答案不小于 $\sum_{i=1}^n(M_i-m_i)$.

因此答案就是 $\sum_{i=1}^n(M_i-m_i)$. 称 $m_i$ 号球为A类球,$M_i$ 号球为C类球,其余为B类球,那么分球要按照A<B<C的顺序分。从左到右扫描,每次乘上有多少人能接此球即可。

D. Sorting a Grid

题意:给一个 $N \times M$ 网格,每个格子不重复地填有 $1$~$NM$ 的正整数。求一种“先重排每行,然后重排每列,再重排每行”的方案使格子从上到下、从左到右依次有序。

笔记:转化为在两顶点集大小各为 $N$ 的 $M$-正则二分图中找 $M$ 个不相交的完美匹配。因为正则二分图必有完美匹配,所以每次任找一个完美匹配作为答案,删掉它以后图仍然是一个正则二分图(或者无边)。

E. Reversing and Concatenating

题意:给定字符串 $S$, 可以操作 $k$ 次,每次操作为用 $U=SS^R$ 的一个长度为 $|S|$ 的子串代替 $S$, 求字典序最小的最终串。

笔记:不妨设 $S$ 的最小字母为 a, 其出现次数为 $L$, 那么 $U$ 的最长连续 a 出现次数必然每次都能翻倍,除非翻倍后大于 $N$. 设第一次最长连续 a 出现次数为 $L$, 若 $2^{K-1}L>N$, 答案是 $N$ 个 a. 否则,除了最后一步外,我们每次都要在末尾暴露出最长连续 a, 最后一步则是在开头。

车队考场做法

每次取 $U$ 最小子串,如果不是最后一次,就把取出的串取反接着做。

题解做法

枚举第一次选谁,后续的最优决策是确定的,直接算。

F. Counting of Subarrays

题意:给定序列。连续至少 $L$ 个 $k$ 可以合成一个 $k+1$. 求原序列有多少个连续子序列可以合成一个数。

笔记:判断一个序列能否合成一个数可以贪心地做:

  1. 若序列只有一种元素,则能合成一个数当且仅当序列长度为 $1$ 或不小于 $L$.
  2. 若序列有多种元素,则找出最小元素的极长连续段,如果有连续段小于 $L$ 则不能合成一个数,否则把 $N$ 个合成 $\left\lfloor\frac NL\right\rfloor$ 个接着做。

考虑整个序列一起做这件事,那么可以设权值 $L_i, R_i$ 分别表示一个元素作为区间左端点、右端点时分别代表多少个元素。

每次取出序列最小值的连续段,先把这些连续段的答案统计进最终答案。

考虑新的 $L_i, R_i$ 的选取,缩起来后最左的点对应了第 $L$ 至第 $2L-1$ 个原先的右端点,次左的点对应了第 $2L$ 至第 $3L-1$ 个原先的右端点,以此类推;左端点的情况类似。

新生成的这些区间上单段统计的答案和原答案重复,要扣除掉。

实现上,拜读 cz_xuyixuan 的代码,很好的思路是,把若干个数的总和对应到原序列的一个区间,从小到大依次插入元素。

posted @ 2019-08-21 17:45  nealchen  阅读(447)  评论(0编辑  收藏  举报