CSP-S 2022 题解
T1 假期计划
\(\tt loj3889\) / \(\tt uoj773\)
首先数据规模是 \(n\le2500\),提示我们用 \(\mathcal O\left(n^2\right)\) 的算法。
我们设存在一条满足题目要求的路径 \(1\to y\to x\),则对于每个 \(x\) 有若干 \(y\),我们需要找出两组 \(x,y\) 使得四个数两两不相同且最大化其权值和。
首先用 \(n\) 遍 bfs 求出任意两点之间的最短路,然后我们就可以得到一个非常暴力的做法,即枚举四个数直接判断是否可行,时间复杂度 \(\mathcal O\left(n^4\right)\)。
我们的枚举肯定是有冗余的,即有大量的枚举根本不可能产生贡献。
首先钦定枚举两个 \(x\),对于每个 \(y\),需要与另外 \(2\) 个数不同,那么对于每个 \(x\),我们只记录其权值最大的 \(3\) 个不同的 \(y\) 即可,因为记录的 \(y\) 互不相同,排名前 \(3\) 的 \(y\) 中至少有 \(1\) 个与对方的 \(x\) 和排名第 \(1\) 的 \(y\) 不同,排名第 \(4\) 的数不可能发挥作用。
T2 策略游戏
\(\tt loj3890\) / \(\tt uoj774\)
这个一看就是大力分讨的鬼畜题。
首先对于先手的数,后手的数只和先手的数的符号有关,若先手出正数则后手出最小的数,出负数则出最小的数,两者出的数的符号决定了最后的符号,所以先手是可以预测到最终数的符号的,所以当最后符号为负时先手会使绝对值最小,否则会使绝对值最大,所以维护 \(6\) 个 ST 表,分别维护 \(A\) 的区间正 / 负数最值以及 \(B\) 的区间最值,暴力分讨即可。
T3 星战
\(\tt loj3891\) / \(\tt uoj775\)
全输出 NO
有 \(45'\)。
首先题目的所谓“反攻”的充要条件即图为内向树森林。
内向树森林的其中一种判定方法是所有点的出度全为 \(1\),我们可以暴力维护每个点的出度以及它的入边集合中当前存在的和不存在的,暴力修改,在没有 \(4\) 操作的情况下时间复杂度是对的,故可以拿到 \(60'\)。
到这里优化已经很难了,利用均摊的思考使时间复杂度正确在 \(4\) 操作存在的情况下不可能,所以得换一个思路。
内向树森林的另一种判定方式是所有边的起点的集合为 \(\{1,2,\cdots,n\}\),所有操作都可以看成对起点集合的操作,那么就是一堆集合修改问题,可以用哈希解决。
直接给 \(1,2,\cdots,n\) 每个数赋一个随机权值,然后用权值和表示一个集合,所有操作都是哈希值的 \(\mathcal O\left(1\right)\) 修改。
T4 数据传输
\(\tt loj3892\) / \(\tt uoj776\)
一道看似恶心实际上思路理清以后并不是很麻烦的题。
做法并不难想,这种静态树上路径问题大多是倍增,那么状态就很一目了然了,\(f_{x,k,i,j}\) 表示从 \(x\) 出发向父亲走 \(2^k\) 步,进入该点时离上一次选中已经走了 \(i\) 步,出去时离上一次选中走了 \(j\) 步的最优解。
首先对于单个点,我们需要先预处理该矩阵,那么我们将转移一一列举:
- 不选中该点的父亲,则 \(f_{x,0,i,i+1}=0\)。
- 选中该点的父亲,则 \(f_{x,0,i,0}=v_{fa}\)。
- 当且仅当 \(k=3\) 时,可以从该点走到与该点相邻的一个点并选中,再回到该点并向父亲处走一步,这种操作只可能在进入该点时离上一次选中已经走了 \(2\) 步出现,否则可以直接到达该点的父亲,转移为 \(f_{x,0,2,2}=\min_{\lang x,y\rang\in E}v_y\)。
那么有了初始矩阵,后面就是先倍增预处理,每次查询边跳父亲边处理矩阵,最后对于每组查询 \(x,y\),首先得知两者到其 LCA 的矩阵,然后进行合并,此时若两者都是刚刚选中则 LCA 被多算了一次,若两者都差两步则还需要在 LCA 周围选最小的一个点作为中转。
细节处理清楚了实现起来并不是很难。