Codeforces 1044F DFS 线段树

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;
}
 
/*
*/

 

posted @ 2019-10-17 14:52  NotNight  阅读(186)  评论(0编辑  收藏  举报