Atcoder ABC394 题解
ABC394
A
枚举串中的所有字符,是 \(2\) 的输出就行。
submission.
B
就按题意说的,按长度为关键字排序即可。
submission.
C
我们使用 std::string::find() 函数,每次从上一次查找到的 WA 的位置的前一个(因为可能会产生新的 AC),总时间复杂度同理双指针,加上 pos 回移了 \(O(n)\) 次,总复杂度 \(O(n)\)。
D
用栈判括号匹配的板子,即遇到左括号就入栈,遇到右括号时如果栈顶不匹配或栈空就 No,最后输出 Yes。
submission.
E
比较有意思的题。
多源最短路,先考虑 Floyd。设 \(f_{i,j}\) 为 \(i\) 到 \(j\) 的回文最短路,转移的时候枚举起始边和终止边,保证这两条边相同。一条路径去掉起始和终止若是回文串,那么这条路径自然是回文串。
于是就有如下代码:
for {x, y}
for {i, j}
if C[i][x] == C[y][j] and C[i][x] not equals to '-'
dis[i][j] := min(dis[i][j], dis[x][y] + 2)
因为不一定是简单路径,所以要将这个代码执行许多次(保证能将边松弛足够多次)。会 TLE。
我们注意到转移只会加 \(2\)。
于是将 \(f_{i,j}\) 看成点 \((i,j)\),去做 BFS。满足上面代码中条件的点对 \((x,y),(i,j)\) 之间有边。正确性原因是图中边权只有 \(2\)。
弄个多源 BFS,具体见代码。
submission.
F
我们首先有个想法,将度数为 \(2\) 或 \(3\) 的点【删掉】,但类似点双,删掉的点要归到多个【块】里去。
我们找一个度数大于等于 \(4\) 的点 DFS,设 \(f_i\) 表示 \(i\) 子树内选三个点连着的最大答案。根比较特殊,选四个。
为什么选三个呢?因为父亲还连着一个。
显然,这三个点一定是儿子中 \(f\) 值最大的三个。
统计答案的时候,若是根就与 \(f\) 值取 \(\max\),否则就把儿子中第四大的(一定大于等于父亲能提供的 \(1\))也加进来算,取 \(\max\)。当然,如果没有四个儿子,只有三个儿子,就将父亲拉进来,与 \(f+1\) 取 \(\max\)。
我们不需要显式地删点,具体见代码。
找前四大的过程可以用四个变量,但谁会这么写呢。
理论复杂度 \(O(n)\),实际复杂度 \(O(n \log n)\)。
submission.
G
考虑对于一个询问,点 \(p\) 到点 \(q\):
首先注意到在图中上下楼和在 \(p\) 点下楼,在 \(q\) 点上楼,中间只用天桥穿梭是等价的。
那下楼下到哪呢?要下到 \(p\) 到 \(q\) 的所有路径中,让路径最小值(瓶颈)最大。
建出 Kruskal 重构树(最大生成树一定是最大瓶颈树),在上面跑跑倍增求路径最大瓶颈就做完了。设起点在 \(x\) 楼,终点在 \(y\) 楼,最大瓶颈在 \(z\) 楼,那么答案就是 \(x+y-2\min(x,y,z)\)。
时间复杂度 \(O((HW+Q)\log(HW))\)。
没有 submission。

浙公网安备 33010602011771号