[CF191C] Fools and Roads - 树上差分,LCA
Description
给出一棵树,给出 m 对点,每对点之间的路径全部加一,最后输出每条边的值。
Solution
剖分求 LCA,然后差分
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6 + 5;
vector<int> g[N];
int n, siz[N], wson[N], dep[N], top[N], fa[N], sum[N];
void dfs1(int p, int from)
{
siz[p] = 1;
for (int q : g[p])
{
if (q == from)
continue;
dep[q] = dep[p] + 1;
fa[q] = p;
dfs1(q, p);
siz[p] += siz[q];
if (siz[q] > siz[wson[p]])
wson[p] = q;
}
}
void dfs2(int p, int from)
{
if (wson[p])
{
int q = wson[p];
top[q] = top[p];
dfs2(q, p);
}
for (int q : g[p])
{
if (q == from || q == wson[p])
continue;
top[q] = q;
dfs2(q, p);
}
}
int lca(int p, int q)
{
while (top[p] != top[q])
{
if (dep[top[p]] < dep[top[q]])
swap(p, q);
p = fa[top[p]];
}
if (dep[p] > dep[q])
return q;
else
return p;
}
void puttag(int p, int val)
{
sum[p] += val;
}
void dfs3(int p, int from)
{
for (int q : g[p])
{
if (q == from)
continue;
dfs3(q, p);
sum[p] += sum[q];
}
}
signed main()
{
ios::sync_with_stdio(false);
cin >> n;
vector<pair<int, int>> edge(n + 2);
for (int i = 1; i < n; i++)
{
int x, y;
cin >> x >> y;
g[x].push_back(y);
g[y].push_back(x);
edge[i] = {x, y};
}
dfs1(1, 0);
top[1] = 1;
dfs2(1, 0);
int k;
cin >> k;
for (int i = 1; i <= k; i++)
{
int x, y;
cin >> x >> y;
int l = lca(x, y);
puttag(x, +1);
puttag(y, +1);
puttag(l, -2);
}
dfs3(1, 0);
for (int i = 1; i < n; i++)
{
auto [x, y] = edge[i];
if (dep[x] > dep[y])
cout << sum[x] << " ";
else
cout << sum[y] << " ";
}
}