Codeforces Round 1028 (Div. 1) 解题报告

Codeforces Round 1028 (Div. 1) 解题报告

A

首先,最后所有的数都会变成 \(d = \gcd_{i = 1} ^ n a_i\)

如果 \(d\)\(a\) 中出现过,直接统计不是 \(d\) 的有几个就行。

否则需要选出一些数凑出 \(d\),然后花 \(n - 1\) 次操作把其他的都变为 \(d\)。前面的最少次数 DP 即可。

预处理所有 gcd,时间复杂度 \(O(n^2)\)

B

考虑直接反着来一个个确定,发现有时选择不唯一。没法做。

观察到每次决策好像都是一个 2-SAT,要么一个是要么另一个是,但是还有一些大小的限制都无法做。

考虑为什么这么难做,发现这是因为每次确定的都是要求某个位置恰好等于一个数字,另一个大于等于的形式,这样就非常难搞。

于是我们大胆转换问题,先只考虑 \(c_i \ge b_i\) 的情况下求出对每个 \(i\)\(a_i\) 的限制 \(l_i\)\(a_i \ge l_i\))。发现所有的倒推都是这样的限制。

最终时 \(l_i = b_i\),倒推一个操作 \((x,y,z)\) 时即令 \(l_x = \max (l_x, l_z)\)\(y\) 一样。一路推到最开始得到一个 \(l_i\),此时令 \(a_i = l_i\) 即可。这个 \(a\) 如果正着推下来能得到 \(b\) 的话就是解,否则无解。

为什么这是对的呢?发现每次决策都是限制一个位置 \(\ge x\) 的形式,所以可以这样构造。这样求得的 \(l\) 一定可以由 \(c_i = b_i\) 倒推而来,因为 \(c_i > b_i\) 时显然不优。同理 \(a_i = l_i\) 也必然是最优解(令每个 \(b\) 尽量小)之一,\(a_i\) 都不行的话增大 \(a\) 正推出来的 \(b'\) 一定不会更小,也即会有 \(b'_i > b_i\),一定会寄。

C

终于有会做的了,看起来题解的要更简单一些,不过无所谓了。

发现每个血量可以首先减去 \(1\),然后目标是变成 \(0\)

发现每个血量大于当前最小值的部分一定是一次次攻击剪掉的,统计这部分并称为冗余量。

考虑 DP,记还能攻击 \(k\) 轮,最小值为 \(i\),冗余量为 \(j\),最后成功的概率为 \(f_{i,j,k}\)。显然有边界:\(f_{i,j,0} = [i = j = 0],f_{0,j,k} = [j \le k]\)

转移有两类(下面 \(i,k > 0\)):

\(j \neq 0\) 时:\(f_{i,j,k} = pf_{i-1, j, k-1} + (1-p)f_{i, j-1, k-1}\)

这是因为泪之剑开大时 AOE 最优,否则单体攻击最优,均显然。

\(j = 0\) 时:\(f_{i,0,k} = pf_{i-1, 0, k-1} + (1-p)\max (f_{i - 1, n-1, k}, f_{i,j,k -1})\)

有得 AOE 当然要 AOE,否则两种选择要么打一个要么不动。

直接做时间复杂度 \(O(H^2nm)\),过不了。

发现第二种情况 \(j\) 维不大于 \(O(n)\),可以先算 \(j \le n\) 的所有 \(f\),时间复杂度 \(O(Hnm)\)

第一种情况可以观察到是一个类似杨辉三角的转移,系数都是确定的,而且因为最后的答案只需要求一个 \(f\),直接枚举它是从哪一个边界转移过来的(\(i,j,k\) 某一个变为零,根据\(\Delta i +\Delta j = \Delta k\),枚举第二个来确定第三个,注意规定优先级以免算重复),算一下系数即可。这是线性的。

D

首先可以假设一开始都选的是 \(a\),初始的数字是 \(A\),每次可以选择异或上 \(a_i \oplus b_i\) 或者不动。

考虑如果每次都是同一个人来决策,这题就是线性基的模板。

有两个人博弈,仍然有一些性质:

  1. 后面的操作选择权力较大。
  2. 每个人仍然是贪心地先保全最高位最优,然后再抢低位。

这仍然是一个线性基的形式,设计如下算法:

从大到小遍历每轮操作,记 \(c_i = a_i \oplus b_i\)

\(c_i\) 插入当前线性基,从高位到低位依次扫描,如果当前位 \(c_i\)\(0\),就跳过;否则如果线性基此位无数字,就插入进来;再否则 \(c_i\) 就异或上此位的数字后往低位扫描。注意每次记录属性(是哪个玩家操控这一轮)。

从高位到低位考虑 \(A\),如果当前位置 \(A = 0\) 而且线性基当前位有数字且是那个要求最终答案最大的,或者都反之,就让 \(A\) 异或上当前位。否则跳过。这样执行一轮就能得知 \(A\) 的最终值了。

E

模板题不会,qwq......

一眼完全背包,\(m\) 过大不可能直接优化的,必须找性质。

有一个经典的不对的贪心:一直选 \(\dfrac {w_i}{c_i}\) 最大的那个,记其为 \((c,w)\)。什么时候它比较对呢?

发现其余的物品不可能选超过 \(c\) 个。否则对 \(c_i\) 的前缀和序列用鸽巢原理,必然可以选出一段区间 \(c_i\) 之和恰好为 \(c\) 的倍数。此时把这些都换成 \((c,w)\) 这个物品,必然不会更劣。

因此分配给别的物品的容量不会超过 \((\max c) ^ 2\)。进一步地,假设询问的 \(r\) 足够大,\(r > (\max c) ^ 2\),则可以有以下算法:

先尽可能地选物品 \((c,w)\),此时 \(ans = \lfloor \dfrac {r}{c} \rfloor w, r' = r \bmod c\)

然后 DP 一个 \(f_m\) 表示当前选了 \(kc+m\) 体积的物品,最大的 \(w\) 之和。

那么有:

\[f_{(m + c_i) \bmod c} \leftarrow f_m + w_i- \lfloor \dfrac {m + c_i}{c} \rfloor w \]

意味着每次填满一次 \(c\) 的容量就需要减掉一个 \((c,w)\)

这不是严格意义的 DP,它是把 \(0, \cdots ,c - 1\) 拆分成一些环,环上转移。观察到在环上转两圈就一定可以转移完(否则有负圈,与 \(\dfrac wc\) 最大矛盾),如此转移即可。最后 \(ans\) 累加上 \(f_{r \bmod c}\) 即可。

放在 DAG 上,需要记录当前在的点 \(u\),钦定 \(\dfrac wc\) 最大点 \(v\),以及当前有没有到过 \(v\)。时间复杂度 \(O(nm \max c)\)

还有一种情况,输入的 \(r\) 不超过 \((\max c) ^ 2\),这部分需要单独处理:直接 DP 当前到了 \(u\),已经选的体积为 \(c\) 即可。第二维有限制了,时间复杂度 \(O(m (\max c) ^ 2)\)

F1

发现这种完全不能维护啊,平衡树套树也不太对,也不能离线,那就考虑根号的结构了。

序列也在翻转来翻转去,应该对操作分块比较好。考虑每 \(B\) 个操作一块:

每过 \(B\) 次操作我们可以重构一次数列,维护出当前 \(pos_i\) 的原始下标。这可以暴力维护,因为 \(B\) 次操作内只把全局划分成了 \(O(B)\) 条线段,可以每次翻转时仅打 reverse 标记并翻转一段线段的位置。重构时再 \(O(n)\) 扫一遍完全可以承受。

这样想通了就好办了。考虑每块内维护每个线段的加入的数字集合(用队列维护),以及这一线段在块所有操作开始前,上一块操作做完时定下标为 \([1,n]\),则这一块的下标。加入,删除(直接全局给一个懒惰标记)和翻转都可以 \(O(B)\) 暴力做,询问则考虑每一个历史块所带来的影响,具体就是从小到大枚举每个元素,如果他还没被删除,这一个块就选它,否则直接删掉它以后也不看了。这样均摊过后也可以接受。

\(B = \sqrt q\),总的时间复杂度 \(O((n+q)\sqrt q)\)

posted @ 2025-06-09 23:22  Vizing  阅读(80)  评论(0)    收藏  举报