Codeforces Round #743 (Div. 2) 解题报告
这里是 Codeforces Round #743 (Div. 2) 的解题报告 qwq,这是一场 Div. 1 和 Div. 2 的比赛,然而这次 Div. 1 出现了计算几何,然而我因为没有学过计算几何而导致止步于 Div. 2。本场比赛时评测机宕机了,导致比赛 unrated,即便如此,本次的题目的亮点仍然是不容忽视的。
到 2021/9/24 为止,笔者并没有想出 CF1572C. Paint 中区间 dp 正确性的证明,所以该题题解只能咕咕咕。
update:CF1572C 请教学长后得到了一个比较感性的证明,写在这里。
CF1573A. Countdown
Description
给定一个 \(n\) 位的十进制数,每次你可以交换任意两位数或者将其减 1,问最少多少次操作可以使其变为 0。多组数据。
数据范围:\(1 \leq t \leq 10^3, 1 \leq n \leq 100.\)
Solution
比较容易想出的一个贪心策略是先将个位清 0,然后在再将各个非 0 位上的数换到个位减掉即可。考虑贪心的正确性,如果将个位清 0 后继续减 1,会使最少增加一位 9 而只使较高的一位减少 1,很容易发现这样做是不优的。
Code
CF1573B. Swap
Description
给定长度均为 \(n\) 的 \(\{a_n\},\{b_n\}\) 两个序列,\(\{a_n\}\) 包含 1 到 \(2n\) 中所有的奇数,\(\{b_n\}\) 包含 1 到 \(2n\) 中所有的偶数,你每一次可以选择一个序列中相邻的两个位置,交换这两个位置上的数,问最少需要多少次交换可以使得 \(\{a_n\}\) 的字典序小于 \(\{b_n\}\),多组数据。
数据范围:\(1 \leq t \leq 10^4, 1 \leq \sum n \leq 10^5\)
Solution
一个有趣的事实是,由于两个序列的元素交集为空,所以字典序的比较只需关注 \(a_1 < b_1\) 是否成立即可。所以我们可以考虑枚举每一个 \(a_i\) 看将其交换到 1 位置后让一个在序列 \(\{b_n\}\) 中,离 1 位置最近的满足 \(b_k > a_i\) 的 \(b_k\),为了快速找到这个 \(b_k\) 的位置,我们只需维护一个后缀最小值 \(pos_i\) 表明在 \(\{b_n\}\) 中排名第 \(i\) 到第 \(n\) 的数的最小位置即可。
Code
CF1572A. Book
Description
有一本 \(n\) 个章节的书,每一个章节都需要在阅读所有其要求的前置章节后,才被可以读懂,一开始你不能理解任何一个章节,每一次你都会依次阅读第 1 章到第 \(n\) 章,遇到无法读懂的章节,就直接跳过。如此一遍遍重复直到你理解了所有章节。问理解所有章节所需要的最小阅读次数,如果无论阅读多少次都不能理解所有章节,则输出 -1,多组数据。
数据范围:\(1 \leq t \leq 2 \times 10^4, 1 \leq \sum n \leq 2 \times 10^5.\)
Solution
首先考虑如何判断有无解,显然有解的充要条件是给定的限制关系的图一定是一张 DAG。考虑如何求出最小的阅读次数,为了方便,我们让边 \(u \rightarrow v\) 表明章节 \(v\) 为章节 \(u\) 的前置章节。我们发现一条边 \(u \rightarrow v\) 对答案有贡献当且仅当 \(u < v\) 成立,这是因为我们是按照升序阅读各个章节的。
所以我们考虑在 DAG 上记忆化搜索,设 \(dp(u)\) 为理解 \(u\) 这个章节需要的阅读次数,根据上面的分析,我们有:
最终最大的 \(dp(u)\) 即为所求。
Code
CF1572B. Xor of 3
Descripiton
给定一个长度为 \(n\) 的 01 序列 \(\{a_n\}\),每次你可以选择相邻的三个位置 \(a_i, a_{i + 1}, a_{i + 2}\,(i \in [1, n - 2])\),将三个位置上的值均修改为 \(a_i \oplus a_{i + 1} \oplus a_{i + 2}\),其中 \(\oplus\) 为异或运算。给出一个不超过 \(n\) 次操作的操作序列,使序列中所有值变为 0,或者报告这是不可能的。多组数据。
数据范围:\(1 \leq t \leq 10^4, 3 \leq \sum n \leq 2 \times 10^5.\)
Solution
经过验算可知,当且仅当 \(a_i, a_{i + 1}, a_{i + 2}\) 有恰有两个或没有一个是 1 时,这时异或值才为 0,否则这个异或值只能为 1。所以我们考虑这样一种策略,在扫到一个非 0 的位置 \(j\) 时,如果从这位置开始的三个数中有两个是 1 就直接将三个数变为 0,否则全部变为 1 并且让 \(j + 2\) 也做同样的判断。显然,这样做最终会使序列变成前面一段连续的 0 和后面一段连续的 1,也有可能得到全 1 串和全 0 串。我们发现现在就很容易判断当前串是否合法,只需按此方法再扫一遍,判断最终是否可以变为全 0 串即可。
我们发现,由于每次更改操作都会间隔 1 个位置,且序列的最后两个位置不可以选,所以扫描一次最多产生 \(\lceil \frac {n - 2} {2} \rceil\) 次操作,故两次扫描的操作的序列的长度也不会超过 \(n\),所以这样得出的答案总是合法的。
Code
CF1572C. Paint
Description
给定一张由 \(n\) 个像素所组成的图片,其中第 \(i\) 个位置的颜色是 \(a_i\),每一次你可以将一段连续的涂有相同颜色的颜色段涂成其他颜色。问最少需要涂色多少次可以将整个图片涂成一种颜色。多组数据。
数据范围:\(1 \leq t \leq 10^3, 1 \leq \sum n \leq 3 \times 10^3, 1 \leq a_i \leq n.\)
数据保证对于初始的图片,每种颜色出现的次数最多为 20.
Solution
我们不妨设 \(f(i, j)\) 表明区间 \([i, j]\) 涂成一种颜色的最小染色次数。我们可以发现对于区间 \([i, j]\),一定有一个最优方案使得整个区间最后染成 \(a_j.\) 这是因为 \(j\) 在区间 \([i, j]\) 的边缘,一定存在一个 \(k \in [i, j - 1]\),使得先将 \([k, j - 1]\) 染成一个颜色,后将 \([k, j]\) 统一颜色,再将整个区间 \([i, j]\) 染成同一颜色。若 \([k, j - 1]\) 按照一种最优方案染完色后与 \(a_j\) 的颜色不同,则要使整个区间颜色相同,只需让 \(j\) 或 \([k, j - 1]\) 整体变颜色,无论变成什么颜色,必然需要使用一次染色,故选择将区间 \([k, j]\) 染成 \(a_j\) 是不劣的,而同理将区间 \([i, k - 1]\) 和 \([k, j]\) 的颜色统一时,都将他们染成 \(a_j\) 也是不劣的。
所以我们可以将 \(f(i, j)\) 重新定义为,将区间 \([i,j]\) 涂成 \(a_j\) 时的最小染色次数。则有:
而这样转移是 \(O(n^3)\) 的,显然会超时。我们发现题目中 “每种颜色出现次数最多为 20” 这个性质我们没有应用,进一步考虑,我们发现区间 \([i, j]\) 的决策点 \(k\),总存在一个决策点有 \(a_k = a_j\) 的性质。这里给出一个感性证明,我们考虑将 \([i, j]\) 这个区间按照 \(a_k = a_j\) 划分成若干小区间 \([i, k_1], [k_1 + 1, k_2], \cdots, [k_m + 1, j]\) 显然这些区间合并时不需要额外使用一次染色的机会,而如果再将其中一个区间拆开作为决策点,那么会少一次将左半部分染成 \(a_j\) 的操作,会多出一次将决策点左右两部分颜色统一的染色操作,所以这样做是不劣的。故我们枚举决策点时,只需枚举 \(a_k = a_j\) 的那一部分即可。这样时间复杂度为 \(O(20 \cdot n^2)\),即 \(O(n^2)\)。
Code
CF1572D. Bridge Club
Description
一场比赛有 \(2^n\) 个预选参赛者,它们从 0 到 \(2^n - 1\) 编号。其中第 \(i\) 名参赛者如果参赛,则其支付的钱数为 \(a_i.\) 比赛要求以两个人组队的形式参加,最多可以有 \(k\) 个队伍。两名参赛者愿意组成一个队伍当且仅当两名参赛者的编号的在二进制中仅有一位不同。求比赛承办方最多可以收到多少钱。
数据范围:\(1 \leq n \leq 20, 1 \leq k \leq 200, 1 \leq a_i \leq 10^6.\)
Solution
本题可以转化为一个费用流模型,我们首先发现当 \(k > 2^{n - 1}\) 时,我们可以至多分成 \(2^{n - 1}\) 组,所以下文的 \(k\) 均为 \(\min(k, 2^{n - 1})\),又发现如果两名参赛者可以在一个队中,则他们编号的二进制表示中 1 的个数的奇偶性一定是不同的。所以我们可以按照奇偶性的标准将参赛者分为两类。考虑费用流的建图,我们建图只需先从源点向辅助点先连一条流量为 \(k\),费用为 0 的边,然后再从辅助点向其它已经分好类的一类点各连一条流量为 1,费用为 \(a_i\) 的边,两类点之间将可以在一个队中的点连一条流量为 1,费用为 0 的边,然后在令所有另一类点向汇点连一条流量为 1,费用为 \(a_i\) 的边。建完图后跑最大费用最大流即可。
但这样建图有一个问题,我们发现点和边的数量均过多,我们难以承受。但是我们发现,我们按位考虑,将每一个参赛编号为 \(i\) 的参赛者与其二进制位在第 \(j\) 位不同的参赛者组成的队所支付的钱数进行排序,然后取前 \(2k\) 个参赛者即可。这样点和边的数量就被缩小在了 \(O(nk)\) 的级别上,这个图和二分图较为相似,故使用 Dinic 算法实现的费用流的复杂度大约只有 \(O((nk)^{1.5})\),可以通过本题。