ABC 429 EF
E
本质上等价于在无权图上求多源最短路和次短路。
求最短路可以直接多源 \(bfs\);而求次短路可以先在求最短路的过程中记录到达每个点的最短路的起点,然后再进行一次完全相同的多源 \(bfs\),转移时额外注意不能从原来的最短路转移过来即可。具体细节见代码。
F
\(ddp\),也称动态 \(dp\)。
由于行数只有 \(3\) 行,我们可以考虑只对列 \(dp\),每一列的状态可以暴力枚举出来,一共只有 \(2^{3}\) 种。
状态定义:\(dp_{i,0/1/2}\):从 \((1, 1)\) 到 \((j, i)\),最短路。
状态转移:对于 \(dp_{i-1,x}\) 到 \(dp_{i,y}\),只需要考虑三个转移:
- 第 \(i-1\) 列内的移动
- 从第 \(i-1\) 列到第 \(i\) 列跨越的一步
- 第 \(i\) 列内的移动
设 \(f_{state,x,y}\):某列的状态为 \(state\),从第 \(x\) 行移动到第 \(y\) 行,需要的最少步数。显然 \(state\) 只有 \(8\) 种。
\(trans:\)
考虑用矩阵表示列之间的转移:设 \(g[i][j]\) 是一个表示从第 \(i\) 列到第 \(j\) 列转移的 \(3 \times 3\) 矩阵,其中矩阵的 \(row\) 表示第 \(i\) 列中的某一行,\(col\) 表示第 \(j\) 列中的某一行。
很显然我们需要一个能高效合并与维护区间信息的数据结构,线段树是不二选择。
考虑线段树的 \(pushup\) 怎么写:两边各自的转移显然要累加到一起,再额外加上中间的一步跨列转移即可。我们可以枚举左子区间到右子区间是从中间的哪一行跨越的。设左右子区间的矩阵为 \(gl,gr\),合并后的矩阵是 \(g\):
\(trans:\)
每次矩阵的合并转移复杂度是 \(O(3^{3})\) 的,最终答案可以用整个区间的 \(g_{0,2}\) 来表示。而单点修改只会改变某一列的状态,相当于第 \(i\) 列本身的矩阵改变,对应线段树只改变了一个叶节点,只需 \(O(\log n)\) 次 \(pushup\) 即可。总复杂度 \(O(3^{3}q\log n)\)。

浙公网安备 33010602011771号