ABC396 EFG 题解

ABC396 EFG 题解

E

套路性地想到通过图来描述约束关系:构造一个 \(n\) 个节点的图分别表示 \(a_{1} \sim a_{n}\),如果存在一个限制 \((x, y, z)\) 表示 \(a_{x} \oplus a_{y} = z\),就在 \(x\)\(y\) 之间连一条边权为 \(z\) 的边。

不妨假设图连通。如果不连通,则分别计算各个连通块的答案再累加。

处理位运算问题的经典套路是逐位考虑,因为位运算的一个优良性质是各比特位之间互不影响。不妨假设所有边权都为 \(0\) 或者 \(1\),也就是只有一个比特位。那么,钦定图中任意一点的点权,则其它点的点权也可以唯一确定。并且,由于异或的性质,如果钦定某个点 \(u\) 的点权为 \(0\) 时,图中没有矛盾,那么把 \(u\) 的点权设为 \(1\),其它点的点权也必须跟着取反,仍然没有矛盾。由于位运算之间各个位互不影响,所以这个结论可以直接拓展到边权不止一个比特位的情况。也就是说,一个图要么没有合法方案,要么可以把一个点的点权任意赋值(而其它点的点权由此推出),得到无数个合法方案。

不妨假设图有合法的赋点权方案,最后考虑如何令点权和最小。先给图中一个点随便设一个点权,得到一个任意的合法方案。然后还是逐位考虑。对于一个比特位,分别统计图中有多少点的点权中该位为 \(1\)\(0\)。如果 \(1\) 的个数少于 \(0\),则无需改变;否则每个点的点权中这一位都取反,得到的方案仍然合法,但是点权和变小了。

\(w = \max a_{i}\),则总时间复杂度为 \(O(m + n \log w)\)

F

\(A\) 数组全局 \(+1\) 就相当于对 \(B\) 数组全局 \(+1\),然后把一些位置变成 \(0\)。具体而言,数 \(x\) 会在第 \((M - x)\) 轮变成 \(0\)。先求出没有修改时全局逆序对数,然后只需考虑每一轮变成 \(0\) 的数对逆序对数量的影响。

由于 \(0\) 是数组中的最小值,而一开始不等于 \(x\) 的数在第 \((M - x)\) 轮一定不为 \(0\),所以可以枚举数组中所有为 \(0\) 的位置,统计以它开头的逆序对数量,这就是第 \((M - x)\) 轮新增的逆序对数。而这些 \(0\) 在上一轮一定是 \(M - 1\),是数组中的最大值,因此还要减去以它们结尾的逆序对数,仍然枚举上一轮所有的 \(M - 1\) 即可。

由于每个数只有 \(1\) 次会变成 \(0\),所以枚举的总时间复杂度为 \(O(n)\)

G

这道题用 FWT 似乎更加直接,可惜我目前不会。本文的做法和官方题解相同,都是使用 dp。(但不得不吐槽官方题解讲的实在太过于抽象,有的式子甚至打错了,所以你也可以把这篇题解看作是官方题解的人话翻译)

下文把题目中的 \(H\)\(W\) 分别记为 \(n\)\(m\)

首先发现 \(m\) 很小,这肯定是我们的切入点。如果确定了有哪些列要翻转,那么显然就可以逐行计算答案。不妨把列的翻转状态看作一个 \(m\) 位二进制数 \(s\),第 \(i\) 位为 \(1\) 表示翻转第 \(i\) 列,否则表示不翻转。对于每一列,也把它的状态记为 \(m\) 位二进制数,第 \(i\) 行记为 \(b_{i}\)

那么,如果列的翻转状态为 \(s\),则第 \(i\) 行翻转后的状态就是 \(b_{i} \oplus s\)。此时如果不翻转第 \(i\) 行,则有 \(\operatorname{popcount}(b_{i} \oplus s)\)\(1\),否则有 \((m - \operatorname{popcount}(b_{i} \oplus s))\)\(1\)。也就是说答案为

\[\sum_{i = 1}^{n} \min(\operatorname{popcount}(b_{i} \oplus s), m - \operatorname{popcount}(b_{i} \oplus s)) \]

如果暴力枚举所有 \(2^{m}\) 种列的翻转状态,总时间复杂度就为 \(O(2^{m}n)\),无法接受。

考虑用 dp 优化求解的过程(本质上是信息复用)。如何设计状态呢?直接设 \(f(s)\) 表示翻转状态为 \(s\) 时的答案肯定是不可行的,因为没有给出任何额外信息。不妨设 \(f(s, i)\) 表示有多少行 \(j\) 满足 \(b_{j}\)\(s\)\(i\) 位不同。这实际上代表着 \(\operatorname{popcount}(b_{j} \oplus s) = i\),因此翻转列之后第 \(j\) 行有 \(i\)\(1\)。于是答案为

\[\boxed{\min_{0 \le s < 2^{m}} \sum_{i = 0}^{m} \min(i, m - i) \cdot f(s, i)} \]

但这样还是不能转移。于是我们强制多设一维状态:设 \(f(s, t, i)\) 表示有多少行 \(j\)最低 \(t\)\(s\)最低 \(t\)\(i\) 位不同,而\((m - t)\) 位全相同。这样设是为了能够逐位转移。转移到第 \(m\) 位的时候,就可以用来统计答案了,因为此时不再要求和 \(s\) 的某个前缀相同。

初始化 \(\forall 1 \le i \le n\)\(f(b_{i}, 0, 0) \gets f(b_{i}, 0, 0) + 1\)

转移:

\[f(s, t, i) = f(s, t - 1, i) + f(s \oplus 2^{t}, t - 1, i - 1) \]

这是讨论了两种情况:如果有一行 \(j\),它只在最后 \(t\) 位和 \(s\) 不同,且不同的位数为 \(i\),那么要么第 \(t\) 位和 \(s\) 相同,这样的行有 \(f(s, t - 1, i)\) 个;要么第 \(t\) 位和 \(s\) 不同,这样的行有 \(f(s \oplus 2^{t}, t - 1, i - 1)\) 个。

dp 的状态数为 \(O(2^{m} m^{2})\),转移的时间复杂度为 \(O(1)\),所以总时间复杂度为 \(O(2^{m} m^{2})\)

AC 记录

posted @ 2025-03-10 21:19  DengStar  阅读(90)  评论(0)    收藏  举报