[NOIP 2016 提高组] 天天爱跑步 题解
对于一个观察点
如果观察点
如果观察点
考虑对每个观察点
那么观察点
当然,肯定不能暴力枚举每一条路径上的观察点
既然是路径,那么就考虑差分。
给
给
然后,对于每个
但是复杂度还是
那么考虑 dsu on tree 去维护桶即可。
最后复杂度是
代码是很好写的。
#include <bits/stdc++.h>
void Freopen() {
freopen("", "r", stdin);
freopen("", "w", stdout);
}
using namespace std;
const int N = 3e5 + 10, M = 2e5 + 10, inf = 1e9, mod = 998244353;
int n, m;
vector< int> G[N];
int w[N];
int siz[N], son[N], dep[N], fa[N];
void init1( int u, int fu) {
siz[u] = 1, fa[u] = fu, dep[u] = dep[fu] + 1;
for ( auto v : G[u]) {
if (v == fu) continue ;
init1(v, u);
siz[u] += siz[v];
son[u] = (siz[v] > siz[son[u]] ? v : son[u]);
}
}
int tot;
int dfn[N], ed[N], rev[N], top[N];
void init2( int u, int topt) {
dfn[u] = ++ tot, rev[dfn[u]] = u, top[u] = topt;
if (son[u]) init2(son[u], topt);
for ( auto v : G[u])
if (v != fa[u] && v != son[u])
init2(v, v);
ed[u] = tot;
}
int lca( int u, int v) {
int tu = top[u], tv = top[v];
while (tu != tv) {
if (dep[tu] < dep[tv]) swap(u, v), swap(tu, tv);
u = fa[tu], tu = top[u];
}
return (dep[u] < dep[v] ? u : v);
}
vector< pair< int, int> > vec1[N], vec2[N];
int ans[N], t1[3 * N], t2[3 * N];
#define py 300000
void dfs( int u, int op) {
for ( auto v : G[u])
if (v != fa[u] && v != son[u]) dfs(v, 0);
if (son[u]) dfs(son[u], 1);
for ( auto p : vec1[u])
t1[p.first + py] += p.second;
for ( auto p : vec2[u])
t2[p.first + py] += p.second;
for ( auto v : G[u])
if (v != fa[u] && v != son[u])
for ( int i = dfn[v]; i <= ed[v]; i ++) {
for ( auto p : vec1[rev[i]])
t1[p.first + py] += p.second;
for ( auto p : vec2[rev[i]])
t2[p.first + py] += p.second;
}
ans[u] = t1[dep[u] + w[u] + py] + t2[w[u] - dep[u] + py];
if (! op)
for ( int i = dfn[u]; i <= ed[u]; i ++) {
for ( auto p : vec1[rev[i]])
t1[p.first + py] -= p.second;
for ( auto p : vec2[rev[i]])
t2[p.first + py] -= p.second;
}
}
signed main() {
ios :: sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> m;
for ( int i = 1; i < n; i ++) {
int u, v; cin >> u >> v;
G[u].push_back(v), G[v].push_back(u);
}
init1(1, 0), init2(1, 1);
for ( int i = 1; i <= n; i ++) cin >> w[i];
while (m --) {
int s, t; cin >> s >> t;
int l = lca(s, t);
vec1[s].push_back({dep[s], 1});
vec1[fa[l]].push_back({dep[s], -1});
vec2[t].push_back({dep[s] - 2 * dep[l], 1});
vec2[l].push_back({dep[s] - 2 * dep[l], -1});
}
dfs(1, 1);
for ( int i = 1; i <= n; i ++) cout << ans[i] << ' ';
return 0;
}