注意到每个操作都是对子树上色,我们先dfs得到dfs序,那么子树u可以表示为区间 [dfn[u], dfn[u] + size[u]) 其中cnt[u]表示子树u的节点数,这样我们就将上色的操作转变成了线段树的区间覆盖。有了dfs序之后,我们就可以再dfs一遍,每到一个节点,就涂色(前提是这个节点有涂色操作),然后统计有多少节点上了色,那么上色数-1就是这个节点的答案。
代码很丑的..
#include<bits/stdc++.h>
using namespace std;
struct edge { int u, v; };
const int MAXN = 100000;
int n, m;
int dcnt, dfn[MAXN + 10];
int child[MAXN + 10], ans[MAXN + 10];
vector<edge> Edge;
vector<int> G[MAXN + 10], color[MAXN + 10];
pair<int, int> opt[MAXN + 10];
void Addedge(int u, int v) {
Edge.push_back((edge){u, v});
G[u].push_back(Edge.size() - 1);
}
void dfs(int u, int fa) {
dfn[u] = ++dcnt;
child[u] = 1;
for(int i = 0; i < G[u].size(); i++) {
edge &e = Edge[G[u][i]];
if(e.v != fa) {
dfs(e.v, e.u);
child[e.u] += child[e.v];
}
}
}
struct seg {
int l, r;
int cnt, sig;
inline int length() {
return r - l + 1;
}
inline void update(seg &lch, seg &rch) {
if(sig) cnt = length();
else {
if(l == r) cnt = 0;
else cnt = lch.cnt + rch.cnt;
}
}
} Tree[MAXN * 4 + 10];
void Build(int u, int l, int r) {
Tree[u].l = l, Tree[u].r = r;
if(l == r) return ;
int mid = (l + r) >> 1;
Build(u * 2, l, mid);
Build(u * 2 + 1, mid + 1, r);
}
void ins(int u, int l, int r, int x) {
if(Tree[u].l > r || Tree[u].r < l) return ;
else if(l <= Tree[u].l && Tree[u].r <= r)
Tree[u].sig += x;
else {
ins(u * 2, l, r, x);
ins(u * 2 + 1, l, r , x);
}
Tree[u].update(Tree[u * 2], Tree[u * 2 + 1]);
}
void dfs2(int u, int fa) {
for(int i = 0; i < color[u].size(); i++) {
int c = color[u][i];
int x = opt[c].first, y = opt[c].second;
ins(1, dfn[x], dfn[x] + child[x] - 1, 1);
ins(1, dfn[y], dfn[y] + child[y] - 1, 1);
}
ans[u] = Tree[1].cnt;
if(ans[u]) ans[u]--;
for(int i = 0; i < G[u].size(); i++) {
edge &e = Edge[G[u][i]];
if(e.v != fa)
dfs2(e.v, e.u);
}
for(int i = 0; i < color[u].size(); i++) {
int c = color[u][i];
int x = opt[c].first, y = opt[c].second;
ins(1, dfn[x], dfn[x] + child[x] - 1, -1);
ins(1, dfn[y], dfn[y] + child[y] - 1, -1);
}
}
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i < n; i++) {
int u, v;
scanf("%d%d", &u, &v);
Addedge(u, v);
Addedge(v, u);
}
dfs(1, 0);
for(int i = 1; i <= m; i++) {
int u, v;
scanf("%d%d", &u, &v);
opt[i] = make_pair(u, v);
color[u].push_back(i);
color[v].push_back(i);
}
Build(1, 1, n);
dfs2(1, 0);
for(int i = 1; i < n; i++)
printf("%d ", ans[i]);
printf("%d\n", ans[n]);
return 0;
}