• [洛谷P3950] 部落冲突


    题目链接:##

    点我

    题目分析:##

    树剖。
    考虑把边权下放到点上进行染色,连通是0,不连通是1,然后有两种处理思路:

    • 维护区间颜色段总数(参考另一篇题解:染色),每次查询判断整段内是否只有一种颜色,若是,判断是否是全连通(可能是全不连通)
    • 维护区间最大值,若是0说明是全连通,若是1说明有不连通边

    和染色一样,注意跳过LCA

    代码:##

    #include<bits/stdc++.h>
    #define int long long
    #define N (1000000 + 5)
    using namespace std;
    
    inline int read() {
        int cnt = 0, f = 1;	char c;
        c = getchar();
        while (!isdigit(c)) {
            if (c == '-') f = -f;
            c = getchar();
        }
        while (isdigit(c)) {
            cnt = (cnt << 3) + (cnt << 1) + c - '0';
            c = getchar();
        }
        return cnt * f;
    }
    
    int nxt[N], first[N], to[N], tot;
    void Add(int x, int y) {
        nxt[++tot] = first[x];
        first[x] = tot;
        to[tot] = y;
    }
    int father[N], dep[N], siz[N], num[N], son[N], top[N], idx;
    void dfs1(int cur, int fa) {
        father[cur] = fa, siz[cur] = 1, dep[cur] = dep[fa] + 1;
        for (register int i = first[cur]; i; i = nxt[i]) {
            int v = to[i];
            if (v != fa) {
                dfs1(v, cur);
                siz[cur] += siz[v];
                if (siz[son[cur]] < siz[v]) son[cur] = v;
            }
        }
    }
    void dfs2(int cur, int tp) {
        num[cur] = ++idx, top[cur] = tp;
        if (son[cur]) dfs2(son[cur], tp);
        for (register int i = first[cur]; i; i = nxt[i]) {
            int v = to[i];
            if (!num[v]) dfs2(v, v);
        }
    }
    
    struct node {
        int l, r;
        int dat;
        int lc;
        int rc;
        #define l(p) tree[p].l
        #define r(p) tree[p].r
        #define dat(p) tree[p].dat
        #define lc(p) tree[p].lc
        #define rc(p) tree[p].rc
    } tree[N * 4];
    
    int Lc, Rc;
    
    void push_up(int p);
    
    void build_tree(int p, int l, int r) {
        l(p) = l, r(p) = r;
        if (l(p) == r(p)) {
            dat(p) = 1;
            lc(p) = rc(p) = 0;
            return;
        }
        int mid = (l + r) >> 1;
        build_tree(p << 1, l, mid);
        build_tree(p << 1 | 1, mid + 1, r);
        push_up(p);
    }
    
    void push_up(int p) {
        lc(p) = lc(p << 1), rc(p) = rc(p << 1 | 1);
        dat(p) = dat(p << 1) + dat(p << 1 | 1);
        if (rc(p << 1) == lc(p << 1 | 1)) --dat(p);
    }
    
    void modify(int p, int x) {
        if (l(p) == r(p)) {
            lc(p) = 1 - lc(p);
            rc(p) = lc(p);
            return;
        }
        int mid = (l(p) + r(p)) >> 1;
        if (x <= mid) modify(p << 1, x);
        if (x > mid) modify(p << 1 | 1, x);
        push_up(p);
    }
    
    int query(int p, int l, int r) {
        if (l > r) return 0;
        if (l(p) == l) Lc = lc(p);
        if (r(p) == r) Rc = rc(p);
        if (l <= l(p) && r >= r(p)) {
            return dat(p);
        }
        long long val = 0;
        int mid = (l(p) + r(p)) >> 1;
        if (l > mid) val += query(p << 1 | 1, l, r);
        else if (r <= mid) val += query(p << 1, l, r);
        else {	
            if (rc(p << 1) == lc(p << 1 | 1)) 
                val += query(p << 1, l, r) + query(p << 1 | 1, l, r) - 1;
             else val += query(p << 1, l, r) + query(p << 1 | 1, l, r);
        }
        return val;
    }
    
    bool chain_query(int u, int v) {
        int res = 0;
        while (top[u] != top[v]) {
            if (dep[top[u]] < dep[top[v]]) swap(u, v);
            res = query(1, num[top[u]], num[u]);
            if (res > 1 || (res == 1 && Lc == 1)) return false;
            u = father[top[u]];
        }
        if (dep[u] < dep[v]) swap(u, v);
        res = query(1, num[v] + 1, num[u]);
        if (res > 1 || (res == 1 && Lc == 1)) return false;
        return true;
    }
    int m, n, x, y;
    int war[N], id;
    char opr;
    void solve() {
        n = read(), m = read();
        for (register int i = 1; i < n; i++) {
            x = read(), y = read();
            Add(x, y); Add(y, x);
        }
        build_tree(1, 1, n);
        dfs1(1, 0); dfs2(1, 1);
        dat(1) = 0;
        for (register int i = 1; i <= m; i++) {
            scanf("%s", &opr);
            if (opr == 'Q') {
                x = read(); y = read();
                if (chain_query(x, y)) printf("Yes
    ");
                else printf("No
    ");
            }
            if (opr == 'C') {
                x = read(); y = read();
                if (dep[x] < dep[y]) swap(x, y);
                war[++id] = x;
                modify(1, num[x]);
            }
            if (opr == 'U') {
                x = read();
                modify(1, num[war[x]]);
            }
        }
    }
    
    signed main() {
        solve();
        return 0;
    }
    
  • 相关阅读:
    java.logging的重定向?
    java.rmi.NoSuchObjectException: no such object in table
    jmx : ClientCommunicatorAdmin Checker-run
    jmx完整示例
    Android studio 下的SDK Manager只显示已安装包的情况
    Android Studio: Error:Cannot locate factory for objects of type DefaultGradleConnector, as ConnectorServiceRegistry
    浅谈Kotlin(二):基本类型、基本语法、代码风格
    浅谈Kotlin(一):简介及Android Studio中配置
    源码浅谈(一):java中的 toString()方法
    ButterKnife注解框架详解
  • 原文地址:https://www.cnblogs.com/kma093/p/11098112.html
Copyright © 2020-2023  润新知