题解:P12449 [COTS 2025] 吸尘 / Usisavač
设结点
首先,假设我们最终停留在
假设某次询问给出一个
我们猜测最优策略是,沿着树的形状 dfs,假设我们现在位于
-
若
\text{high}_u \le r ,就把吸尘器插在u 的位置,将u 子树内所有边都清理一遍,拔掉插座。 -
若
\text{high}_u > r ,那么把吸尘器插在u ,将边(u, v) 清理后回到u ,将插座拔掉后正常走到v 。
对于一条边
这个容易前缀和维护,单次询问
现在我们通过说明,对于每条边
考虑它是如何被清理的,如果吸尘器在
如果吸尘器在
#include <iostream>
#include <vector>
using namespace std;
const int kN = 3e5 + 5;
int n, q;
vector<int> e[kN];
int dep[kN], high[kN], p[kN];
void Dfs (int u, int r) {
for (auto v : e[u]) {
if (v == r) continue;
dep[v] = dep[u] + 1;
Dfs(v, u);
high[u] = max(high[u], high[v] + 1);
}
}
int main () {
cin.tie(0)->sync_with_stdio(0);
cin >> n >> q;
for (int i = 1, u, v; i < n; ++i) {
cin >> u >> v;
e[u].push_back(v);
e[v].push_back(u);
}
Dfs(1, 0);
int mxd = 0;
for (int i = 1; i <= n; ++i) mxd = max(mxd, dep[i]);
for (int i = 2; i <= n; ++i) ++p[high[i]];
for (int i = 1; i <= n; ++i) p[i] += p[i - 1];
for (int i = 1, r; i <= q; ++i) {
cin >> r;
cout << 4 * (n - 1) - mxd - 2 * p[r - 1] << ' ';
}
cout << '\n';
return 0;
}