Codeforces 1044F DFS 线段树
考虑dfs的非树边全部都是反祖边, 对于新加的一条边那么所有它一定是一条反祖边, 那么用线段树把
对于这条边不可行的点全部ban掉就好了。
#include<bits/stdc++.h> using namespace std; const int N = (int)2e5 + 7; const int LOG = 18; set<pair<int, int>> S; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 struct SegmentTree { int mx[N << 2], cnt[N << 2], lazy[N << 2]; inline void pull(int rt) { if(mx[rt << 1] > mx[rt << 1 | 1]) mx[rt] = mx[rt << 1], cnt[rt] = cnt[rt << 1]; else if(mx[rt << 1] < mx[rt << 1 | 1]) mx[rt] = mx[rt << 1 | 1], cnt[rt] = cnt[rt << 1 | 1]; else mx[rt] = mx[rt << 1], cnt[rt] = cnt[rt << 1] + cnt[rt << 1 | 1]; } inline void push(int rt) { if(lazy[rt]) { mx[rt << 1] += lazy[rt]; mx[rt << 1 | 1] += lazy[rt]; lazy[rt << 1] += lazy[rt]; lazy[rt << 1 | 1] += lazy[rt]; lazy[rt] = 0; } } void build(int l, int r, int rt) { lazy[rt] = 0; if(l == r) { mx[rt] = 0; cnt[rt] = 1; return; } int mid = l + r >> 1; build(lson); build(rson); pull(rt); } void update(int L, int R, int val, int l, int r, int rt) { if(R < l || r < L || R < L) return; if(L <= l && r <= R) { mx[rt] += val; lazy[rt] += val; return; } push(rt); int mid = l + r >> 1; update(L, R, val, lson); update(L, R, val, rson); pull(rt); } int getAns() { return mx[1] == (int)S.size() ? cnt[1] : 0; } }; int n, q; int depth[N], pa[N][LOG]; int in[N], ot[N], dfs_clock; vector<int> G[N]; SegmentTree Tree; void dfs(int u, int fa) { in[u] = ++dfs_clock; depth[u] = depth[fa] + 1; pa[u][0] = fa; for(int i = 1; i < LOG; i++) { pa[u][i] = pa[pa[u][i - 1]][i - 1]; } for(auto &v : G[u]) { if(v == fa) continue; dfs(v, u); } ot[u] = dfs_clock; } int getLca(int u, int v) { if(depth[u] < depth[v]) swap(u, v); int d = depth[u] - depth[v]; for(int i = LOG - 1; i >= 0; i--) { if(d >> i & 1) { u = pa[u][i]; } } if(u == v) return u; for(int i = LOG - 1; i >= 0; i--) { if(pa[u][i] != pa[v][i]) { u = pa[u][i]; v = pa[v][i]; } } return pa[u][0]; } int go(int u, int step) { for(int i = LOG - 1; i >= 0; i--) { if(step >> i & 1) { u = pa[u][i]; } } return u; } void modify(int u, int v, int val) { if(depth[u] < depth[v]) swap(u, v); int lca = getLca(u, v); if(lca != v) { Tree.update(in[u], ot[u], val, 1, n, 1); Tree.update(in[v], ot[v], val, 1, n, 1); } else { if(pa[u][0] == v) { Tree.update(1, n, val, 1, n, 1); return; } v = go(u, depth[u] - depth[v] - 1); Tree.update(in[u], ot[u], val, 1, n, 1); Tree.update(1, in[v] - 1, val, 1, n, 1); Tree.update(ot[v] + 1, n, val, 1, n, 1); } } int main() { scanf("%d%d", &n, &q); for(int i = 1; i < n; i++) { int u, v; scanf("%d%d", &u, &v); G[u].push_back(v); G[v].push_back(u); } dfs(1, 0); Tree.build(1, n, 1); while(q--) { int u, v; scanf("%d%d", &u, &v); if(u > v) swap(u, v); auto it = S.find(make_pair(u, v)); if(it == S.end()) { S.insert(make_pair(u, v)); modify(u, v, 1); } else { S.erase(it); modify(u, v, -1); } printf("%d\n", Tree.getAns()); } return 0; } /* */