zoukankan      html  css  js  c++  java
  • 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
    ", Tree.getAns());
        }
        return 0;
    }
     
    /*
    */
  • 相关阅读:
    03:矩形分割 (二分)
    09:膨胀的木棍 (二分+角度计算)
    A Cubic number and A Cubic Number (二分) HDU
    B
    08:不重复地输出数 (set)
    10:河中跳房子 (二分)
    07:和为给定数 (二分)
    04:网线主管 (二分)
    河中跳房子
    010:输出前k大的数
  • 原文地址:https://www.cnblogs.com/CJLHY/p/11692021.html
Copyright © 2011-2022 走看看