CSP-S 2022 题解
A 假期计划
若 \(u\) 转车不超过 \(k\) 次可以到达 \(v\),相当于 \(u\leadsto v\) 的最短路长度不超过 \(k+1\)。
对于每个点 \(u\),我们首先预处理满足如下条件的点 \(v\) 中,分数第 \(1\sim 3\) 大的,设这三个点分别为 \(a_{u,0},a_{u,1},a_{u,2}\):
- \(v\neq u,v\neq 1\);
- \(1\) 可转车不超过 \(k\) 次到达 \(v\);
- \(v\) 可转车不超过 \(k\) 次到达 \(u\)。
然后枚举景点 B 和景点 C,设它们分别是 \(u\) 和 \(v\),对于 \(a_{u,i}\) 作为景点 A,以及 \(a_{v,j}\) 作为景点 D 的九种情况,分别检查其是否合法(也就是 \(a_{u,i}\neq a_{v,j},a_{u,i}\neq v,a_{v,i}\neq u\)),若合法则更新答案即可。
为什么需要预处理第 \(1\sim 3\) 大的?因为可能出现 \(a_{u,0}=a_{v,0},a_{u,1}=v,a_{v,1}=u\) 的情况,此时不得不使用 \(a_{u,2}\) 或 \(a_{v,2}\)。
时间复杂度 \(O(n^2)\),代码实现。
B 策略游戏
由于先手的目标是让乘积尽量大,后手的目标是让乘积尽量小,所以一组询问 \((l_1,r_1,l_2,r_2)\) 的答案就是:
显然,内层和外层都只有五种取值的可能:取最大/最小的正值,最大/最小的负值,以及零。对于零,直接记录区间中是否有零即可。对于剩下四种,用 ST 表维护即可。
时间复杂度 \(O(n\log n+m\log m+q)\),代码实现。
C 星战
能进行反击的充要条件是:每个点的出度都恰好为一。这是显然的,因为这样会形成若干内向基环树,自然满足题目中的条件。
对于任意的点 \(u\),考虑给 \(u\) 的所有出边都赋一个相同的权值 \(V_u\),这个权值在 \([0,2^{64})\cap \mathbb{Z}\) 中均匀随机。我们预先算出 \(dst=\operatorname{xor}_{i=1}^n V_i\),并维护整张图的边权的异或和 \(x\)。能进行反击的必要条件就是 \(x=dst\)。
但这样我们只能判定每个点的出度为奇数。考虑到此时每个点的出度都至少为 \(1\),若某个点的出度大于一,那么总边数就会大于 \(n\)。因此我们再记录当前的边数 \(e\),能进行反击的充要条件就是 \(e=n\) 且 \(x=dst\)。
时间复杂度 \(O(n+m+q)\),代码实现。
D 数据传输
钦定 \(1\) 是树的根。设二元组 \((u,i)\)(\(0\le i<k\))表示“当前位于 \(u\) 下方的某个到 \(u\) 的距离为 \(i\) 的点”这种状态。
考虑使用倍增。我们只需要对于每个点 \(u\) 算出 \((u,i)\) 转移到 \((\mathrm{fa}_u,j)\) 的最小代价,然后对于每个 \(x\),倍增预处理 \((u,i)\) 到 \((\mathrm{anc}_{x,u},j)\) 的最小代价即可,其中 \(\mathrm{anc}_{x,u}\) 表示 \(u\) 的第 \(2^x\) 级祖先。而转移只有四种情况:
- 不需要移动;
- 从当前点跳到 \(u\);
- 从当前点跳到 \(\mathrm{fa}_u\);
- 若 \(k=3\),从当前点跳到某个到 \(\mathrm{fa}_u\) 距离为 \(1\) 的点。
对于每种 \(i,j\) 的取值,我们都可以讨论出选择哪种情况是最优的,具体见代码实现。我们可以将这些 \((i,j)\) 对应的最小代价写成一个 \(k\times k\) 的矩阵,那么信息的合并就相当于做一个类似矩阵乘法的东西。
对于某个查询 \((u,v)\),设 \(t=\operatorname{LCA}(u,v)\),我们倍增算出 \(u\to t\) 的信息 \(A\) 和 \(v\to t\) 的信息 \(B\),答案就是 \(\min_{i+j\le k} \{v_u+v_v+A_{0,i}+B_{0,j}-[i=0\land j=0]\times v_t\}\)。
时间复杂度 \(O(k^3(n+q)\log n)\),代码实现。