题解:P16905 [CCO 2026] Tree Traversals
_Communist · · 题解
来个普及组小朋友都会写的在线线性实现,懒得卡常,但是好写就对了。
首先有深度不降的限制,不妨记深度为
这里讲讲如何简单求出
:::info[这一部分的代码]
void getlca() {
auto check = [&](int u, int d) { return vec[d][0] >= dfn[u] && vec[d].back() <= dfr[u]; };
//vec[d] 存储了深度为 d 的节点的 dfn
int u = 0;
for (int i = 1; i <= n; ++i) {
if (check(i, m) && (!u || dep[i] > dep[u])) u = i;
}
lca[m] = u;
for (int i = m - 1; ~i; --i) {
while (fa[u] && !check(u, i)) u = fa[u];
lca[i] = u;
}
}
:::
接下来考虑相邻层之间的移动,假设
此时只剩下
于是在求
:::info[求答案部分的代码]
void solve() {
int lim = 0;
for (int i = 0; i <= m; ++i) {
lim = max(lim, (i - dep[lca[i]]) << 1);
}
fill(ans, ans + 1 + n, 0);
if (lim > n) return;
int res = 1;
for (int i = 0; i <= m; ++i) tim(res, fac[vec[i].size()]);
fill(ans + 1 + lim, ans + 1 + n, res);
res = 1;
for (int i = 0; i <= m; ++i) {
int x = 0;
if (lst[i] && lim == ((i - dep[lca[i]]) << 1)) {
for (int v : vec[i]) if (v >= dfn[lst[i]] && v <= dfr[lst[i]]) ++x;
} else x = vec[i].size();
tim(res, x), tim(res, fac[(int)vec[i].size() - 1]);
}
ans[lim] = res;
}
:::