ARC220

AtCoder Regular Contest++ 220

闲话

年轻人老年人的第一场 ARC Div.1,重回 \(2900\) 了,但还是暴露出很多问题。

首先是 B 题,一开始就意识到大概率是欧拉回路相关了,但还是在代数表示上硬修企图绕过求出回路之后调整解的步骤,浪费了大量时间。

然后是 C 题,意识到转移结构是一个凸包是没有困难的,但没有正确利用凸性来优化,类似于 slope trick 的思路可以写到很短,我的做法是直接利用凸包在斜率上的性质,线段树优化转移,写了 4KB 代码调了半天我也不知道自己在干什么。

最后是 D 题,其实 C 调一半感觉不一定能调出来就开始考虑这家伙了,场上想到了一开始的从完全图上路径转化到邻接矩阵,再转化到平面图四联通意义下路径这一步,然后我的思路是类似于 NOI2024D1T2 那样 DP 出最优决策,考虑一些和当前处理区域的轮廓线有关的转移,但事实上不存在任何一类轮廓线上的子结构可以构造出题目要求长度的路径,于是爆了,意识到可以直接分析出这个结论的时候大概只剩半小时多一点,再回去想归纳构造已经来不及了,把 C 调了遗憾离场。

E 貌似和今年集训队互测的 一个题 是类似的,什么罐子我说,看后面能不能补吧。


A (构造、Ad-hoc、*1600):

注意到 \(\frac{1}{a^2} = \frac{1}{4a^2} + \frac{1}{4a^2} + \frac{1}{4a^2} + \frac{1}{4a^2}\),也即如果一个合法序列 \(A\) 中含有数字 \(x\),将其替换为四个 \(2x\) 也是合法的。

那么这样会让序列长度增加 \(3\),也就是说,只需要构造 \(n \bmod 3 = 0, 1, 2\) 的极小合法序列,然后就可以增量地构造出它们以上的所有可能方案。

对于 \(n = 1\) 有 \(\{1\}\) 是合法的,对于 \(n = 6\) 有 \(\{2, 2, 2, 3, 3, 6\}\) 合法,对于 \(n = 8\) 有 \(\{2, 2, 3, 3, 3, 3, 6, 6\}\) 合法。

那么直接增量构造即可,可以直接打表得出对于更小的不包含在上面的 \(n\),必定是无解的。

时间复杂度 \(\mathcal{O}(n)\)。

ac link


B (并查集、欧拉回路、Ad-hoc、*2200):

首先有一个最基础的观察:因为交换过程中不能选择同一个置换环中的两个点,所以如果存在 \(n\) 阶排列 \(p\),使得 \(\{a_{p_1}, a_{p_2}, \dots, a_{p_n}\}\) 为 \(\{a_1, a_2, \dots, a_n\}\) 排列后的结果,那么 \(p\) 建出图之后应为单个置换环。

这个限制本身是困难的,考虑先任意建环然后调整成一个。所以初始时可以任意贪心地匹配,如果两个环中有任意一对 \(A\) 或 \(B\) 相等,可以直接交换从而使得连边交错,两个小环合并为一个大环。其次,一个环内如果能完美匹配,即每类 \(A\),\(B\) 数量均相等,那么在合并时必须要丢一个匹配。非完美匹配的环可以任意取一个未匹配位置用于交换,则不产生代价。

则贪心之后减去完美匹配的环的数目即为最终答案,特判是只有一个环的情形不需要合并。

另一个角度是在大环上走一步相当于 \(a_i\) 走到 \(a_{p_i}\) 状物,然后我们要最大化满足这个操作可达的位置,那么等价于最小化跳到其余点的次数,这等价于加 \(k\) 条边使得原图存在欧拉回路,最终答案即为 \(n - k\)。那么对任意一个连通图都有 \(k = \sum_{i = 1}^{n} \max\{0, \deg_{\text{out}}(i) - \deg_{\text{in}}(i)\}\)。对非连通图再考虑一下增加一条边使得两个连通块之间可达的代价,对不存在欧拉回路的连通分量则可以任取一条边操作,不需要增加。

环的结构不重要,可以直接类 BFS 或并查集维护,时间复杂度 \(\mathcal{O}(n)\) 或 \(\mathcal{O}(n \alpha(n))\)。

ac link


C (DP、凸性优化、Slope Trick、*2600):

令 \(b_i\) 表示所有操作结束后的 \(a_i\),容易发现因为可以操作单点,又因为字典序的比较规则,对于两个能继续操作使其递减的位置,优先调整下标更小的那一个必定不劣,所以每个位置要么是 \(0\) 要么是 \(a_i\)。

所以考虑一个从左到右的,基于贪心策略的 DP 来确定每个前缀一共花费的次数,从而确定当前这个下标上的数能否被调成 \(0\)。

令 \(f_i\) 表示考虑了 \(0 \sim i\),默认 \(f_0 = 0\),包含了 \(a_i\) 的区间操作的次数。因为我们用 \(f_{i - 1}\) 次操作将 \(a_{i - 1}\) 调成 \(b_{i - 1}\),将这些操作扩展至 \(i\),则必定有此时 \(a_i\) 的取值 \(X = (a_i + f_{i - 1}) \bmod m\)。我们可以通过调整一部分区间操作的右端点为 \(i - 1\) 来将 \(X\) 调成最小值。因为 \(f_i \geq 0\) 的限制所以可能无法做到直接令 \(X = 0\),这种情况下,考虑对之前删去间使得 \(b_j = 0\) 的位置,通过加 \(m\) 次区间操作使其保持不变,同时区间的右端点延申至 \(i\),从而将 \(X\) 调成 \(0\)。我们需要对每个位置求此时让 \(b_i = 0\) 的额外操作次数,这个可以类似于反悔贪心处理,用一个小根堆维护之前 \(X\) 可以调为 \(0\) 位置的 \(m - X\),也就是实际上将其延申至当前位置的备选的方案,此时如果有符合条件的,使操作次数总和不超过 \(k\) 的堆顶元素就取用,否则当前位置必定无解。通过这个反悔贪心可以将每个位置能否调成 \(0\) 实时维护出来。

另一个更加 naive 的思路是,考虑设每个位置调到 \(0\) 最小次数为 \(t_i\),实际操作次数为 \(p_i\),最小操作总次数必定为 \(\sum_{i=1}^{n} \max\{0, p_{i} - p_{i - 1}\}\),其中 \(p_0 = 0\)。所以设 \(f(i,j)\) 表示考虑位置 \(i\) 的实际操作次数为 \(j \times m + t_i\),最小总操作次数是多少,则有两种转移:

  • \(t_i \geq t_{i - 1}\),即上面可以直接调为 \(0\) 的情况,它必定不会从更小的 \(j\) 转移过来,所以只能从 \(j + 1\) 转移,也不会从更大的转移因为那样必定不如停在 \(j + 1\) 优,也就不会转移到 \(f(i,j)\) 了。有 \(f(i,j) = \min\{f(i - 1, j + 1), f(i - 1, j) + t_i - t_{i - 1}\}\)。

  • \(t_i \lt t_{i-1}\),这种情况下至多从 \(j - 1\) 转移,原理也是类似的,所以有 \(f(i,j) = \min\{f(i - 1, j), f(i - 1, j - 1) + M + t_i - t_{i - 1}\}\)。

这样有一个 \(\mathcal{O}(n^2)\) 的 DP,它本质上是类似于 \(h_i = \min\limits_{j \in \mathbb{R}} f_j + g_{i - j}\) 状物,也就是两个函数的闵可夫斯基和,对于 \(f(i,j)\) 和 \(t_{i} - t_{i - 1}\) 这两个凸函数,转移过程的闵可夫斯基和也必定是凸函数。转移方程可以视作与一个定义域有限的一次函数进行卷积下界面,直接将两个维护斜率的堆合并即可,又因为这个一次函数定义域长度为 \(2\) 所以直接插入两次即可。

赛时想到 \(\mathcal{O}(n^2)\) 的 DP 之后就一直想势能线段树的事,还差点写不对,浪费一个小时,怎么回事呢。

时间复杂度 \(\mathcal{O}(n \log n)\)。

ac link


D (图论、构造、Ad-hoc、*3400):

还是死在了后半段思路收敛的部分,想得不够清楚导致的,错失了场切第一个 \(3400\) 的机会。

由于边不能重复经过,考虑将一条边 \((i,j)\) 转化为 \(n \times n\) 网格图上的一个格子,这里钦定 \(i \lt j\),那么所有可能用到的格子会组成一个上三角(不包含对角线)。

那么考虑题目给定的有关路径的约束,因为 \(|v_{i + 2} - v_i| = 1\),又因为 \(v_i \ne v_{i + 1} \ne v_{i + 2}\),所以 \(v_{i + 1}\) 要么同时小于 \(v_i, v_{i + 2}\),要么同时大于 \(v_i, v_{i + 2}\),又因为差的绝对值恰为 \(1\),所以 \((v_i, v_{i + 1}), (v_{i + 1}, v_{i + 2})\) 必定是四联通意义下相邻的两个格子。

由此我们看出完全图上一条合法路径对应网格图上一条不经过重复点的路径,又因为完全图经过的相邻的三条边必定不会经过同一个点,所以网格图上也必定不存在连续三个格子在同一行或同一列,也就是说走一步就必须改变一次方向。那么问题转化为,在 \(n - 1\) 阶上三角网格图中,选出一条四联通意义下的简单路径,使得:

  • 每一步行走方向都与上一步不同;
  • 长度必须 \(\geq \frac{(n - 2)^2}{2}\)。

因为总共的点数为 \(\frac{n(n + 1)}{2}\),而限制为 \(\frac{(n - 2)^2}{2}\),所以总共只能缺少 \(1.5n + 1\) 个格子,限制十分紧,考虑归纳构造。

当 \(n = 2\) 时只有一个格子,不需要动;

当 \(n = 3\) 时直接 RD 即可;

当 \(n = 4\) 时可以 RDRD 从而通过 \(5\) 个格子;

当 \(n = 5\) 时可以 RDRDRD 通过 \(7\) 个格子;

上面是比较简单的部分,因为 \(n\) 比较小所以函数发散的尺度不大,直接用确保合法性的 RD 序列拼起来就好了。

当 \(n = 6\) 时,可以用 RDRURDRDLDRD 来实现一个类似于 Zig-Zag 的构造,可以通过 \(13\) 个格子。

上面是 base-case,下面考虑归纳构造。

当 \(n\) 为偶数时,利用左上角的 \((n - 5) \times (n - 5)\) 格子找到一条 \((1, 2) \to (n - 5, n - 4)\) 的路径,那么可以将 \(n\) 归纳到 \(n - 4\) 的子问题,接下来可以利用下面两步走到 \((n - 1, n)\):

  • 在 \(n - 3\) 和 \(n - 2\) 两列中向上 Zig-Zag;
  • 在 \(n - 1\) 和 \(n\) 两列中向下 Zig-Zag。

在此过程中,每次 \(n \to n - 4\) 会浪费 \(6\) 个格子,符合要求。

当 \(n\) 为奇数时,我们发现正常的逐行/逐列归纳构造行不通了(这也是考场上寄掉的地方),如果每次还是按照 \(n \to n - 4\) 操作,因为多了一列,每次 \(n \to n - 4\) 会浪费 \(10\) 个格子,也就是最终会浪费 \(2.5n + \mathcal{O}(1)\) 个格子,这是行不通的。

此时就要考虑和单一轮廓线不一样的结构了,一个常见的思路是想办法将最外层的一圈通过某些方式删掉,从而归纳到更小的结构。具体地说:

  • 从起点 \((1,2)\) 重复 RD 操作直至 \((n - 3, n - 1)\)。
  • 利用第 \(n - 1\) 和第 \(n\) 列向上 Zig-Zag 至 \((2, n - 1)\)。
  • 利用第 \(1\) 行和第 \(2\) 行向左 Zig-Zag 至 \((2, 5)\)。
  • 任意取一边的 L 形长度为 \(2\) 简单路径移动至 \((3, 6)\)。
  • 那么此时问题转化为第 \(3 \sim n - 5\) 行,第 \(5 \sim n - 2\) 列的子问题,实现了 \(n \to n - 6\) 的过程。

在此过程中,只浪费了 \(9\) 个位于第 \(1, 2\) 行和第 \(n - 1, n\) 列的格子,并且 \(\mathcal{O}(1)\) 常数项只会在第一次操作时出现,这样最终少的格子数目是 \(1.5n + 1\),符合要求。

时间复杂度 \(\mathcal{O}(n^2)\)。

ac link


posted @ 2026-09-28 00:44  Twistedmind  阅读(5)  评论(0)    收藏  举报