USACO 2022 Dec 铂金组题解

有生之年终于 AK 一次 Pt 组了,发个题解玩玩。

T1 - Breakdown

大部分情况下,题目里若存在一个很小的 \(k\) 这样的角色,都是因为它在复杂度指数上(包括但不限于 \(2^{\operatorname{poly}(k)}\)\(n^{\operatorname{poly}(k)}\))。

时光倒流变成加边。考虑折半,维护 \(1\) 到每个点 / 每个点到 \(n\) 边数为 \(1 \sim 4\) 时分别的最短距离。询问时 meet in the middle,\(\mathrm O(n)\)

怎么维护?考虑到 \(k\) 大概率在指数上,而 \(k\leq 4\),一个朴素的方法是暴力枚举 \(k\) 步的每一步,\(\mathrm O(n^k)\)。但最多只能接受 \(\mathrm O(n)\) 时间内更新一次。

设加的边为 \(x \to y\)。枚举这条边是 \(k\) 条边中的哪条,更新。其实是能平均一次 \(\mathrm O(n^{k - 2})\) 更新而非 \(\mathrm O\!\left(n^k\right)\) 的,因为 \(x, y\) 本身就确定了两个点。另外,如果这条边充当第一条从 \(1\) 出发的边的话,只能多确定一个点,但 \(x = 1\) 的边本身就只有总边数的 \(\frac 1 n\),恰好抵消了。

这样 \(k = 4\) 时是平方,还是不行。再注意到 \(k = 4\) 时可以利用 \(k = 2, 3\) 的信息;而 \(k = 2\)\(\mathrm O(1)\) 又有点浪费,可以升级一下,\(\mathrm O(n)\) 维护两两点之间跨两步的最短路。利用这些信息,分类讨论可知 \(k = 4\) 时加入的边无论充当第几条,都可以在 \(\mathrm O(n)\) 时间内完成更新。

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

T2 - Making Friends

当奶牛 \(x\) 离开时,设其所有邻居从小到大依次为 \(y_1, y_2, \cdots, y_k\)

如果 \(k = 0\) 直接跳过。

否则,将 \(y_i\) 互相连接,显然等效于将 \(y_1\)\(y_{2 \sim k}\) 相连。这就是个邻接表的合并,线段树合并或 set 启发式合并即可。

方便起见,给边按 \(x \to y (x < y)\) 定向。每次奶牛离开时邻接表大小之和减去初始边数就是答案。

T3 - Palindromes

先考虑怎么算某个串的 cost,这部分比较简单。如果 G 和 H 的数量都是奇数,那就 -1。否则设其中 G 的位置依次为 \(p_1, p_2, \cdots, p_k\)。显然在最优移动的过程中不会改变两个 G 的相对位置,\(p_i\)\(p_{k - i + 1}\) 配对。要将一对 \(p_i, p_j\) 移动到对称的位置,显然至少要花 \(f(i, j) = |(M - p_i) - (p_j - M)| = |2M - p_i - p_j|\) 步数,其中 \(M = \frac{1 + L}2\)\(L\) 为串长。所以 cost 的一个下界是

\[[2 \nmid k]|p_{(1 + k) / 2} - M| + \sum_{i = 1}^{\lfloor k / 2\rfloor} f(i, k - i + 1) \]

容易证明,这个下界能取到:只要从外层往内层依次对齐,将靠内的往外移,对齐总能进行。

-1 和 \(2 \nmid k\) 的那项容易先 \(\mathrm O(n^2)\) 处理掉。接下来考虑每一对 \(p_i, p_j (i < j)\) 的贡献。那就是所有不为 -1 的,让 \(p_i, p_j\) 配对的子串 \([l, r]\),令它们的 \(M = \frac{l + r}2\),对 \(f(i, j)\) 求和。

容易想到将 \(i + j\) 相等的对放一起处理,从外往内,每次加入所有 \((l, r) \in (p_{i - 1}, p_i] \times [p_j, p_{j + 1})\) 并查询贡献,这样每对 \((l, r)\) 只会被加入一次。如果 \(f(i, j)\) 不带绝对值的话,那直接做完了;可惜是带绝对值的,那只能把 \(2M\) 装到 BIT 里,分 \(2M \lesseqgtr p_i + p_j\) 两半算贡献,\(\mathrm O(n^2 \log n)\)

奈何它 7500 也卡不了我。共要 \(\frac{c^2}2 + \frac{n^2}2\) 次 BIT 操作,其中 \(c\) 是 G 出现次数,常数极小!一个卡常技巧是:G 还是 H 不重要,可以让出现次数较少的作为 G,这样最多要 \(\frac 5 8 n^2\) 次 BIT 操作。

这个方法是可以改进为 \(\mathrm O(n^2)\) 的。注意到,每次查询的左右端点 \(p_i, p_j\) 分别单调,于是直接单点修改数组并暴力移动指针,就可以 \(\mathrm O(1)\) 修改,且每个 \(i + j\) 相等组的查询操作都在 \(\mathrm O(n)\) 时间内解决。

posted @ 2022-12-20 23:07  ycx060617  阅读(738)  评论(3编辑  收藏  举报