zoukankan      html  css  js  c++  java
  • CodeForces

    题目

    传送门

    翻译可能有点不太明白。其实这里的加边和删边是原来有边就删,没有就加。

    然后这里保证了 (u_i<v_i),所以边是不会有正反情况的。

    解法

    可以用线段树分治来优化,具体做法就是将每条边存在的时间化成一个区间挂在线段树上,因为大区间包含的小区间一定包含大区间的边,所以我们可以只在大区间加边,将边的信息插入到并查集后遍历小区间,回退时删掉这个区间加的边即可。二分图判定就是带权并查集的基操。

    具体讲一下带权并查集的写法。

    ( ext{unionSet})

    void unionSet(const int u, const int v, const bool flag) {
        int x = findSet(u), y = findSet(v);
        if(dep[x] < dep[y]) swap(x, y);
        if(dep[x] == dep[y]) ++ dep[x], s[++ tp] = -x;
        f[y] = x; s[++ tp] = y; c[y] = flag;
    }
    

    这其实就是按秩合并。因为要回退,我们又有两种更改的操作,所以把一种操作的栈赋值负数。而 (c) 就是维护与父亲是否在同部。

    ( ext{Restore})

    void Restore(const int ntp) {
        int u;
        while(tp > ntp) {
            u = s[tp]; -- tp;
            if(u > 0) f[u] = u, c[u] = 0;
            else -- dep[-u];
        }
    }
    

    ( m ntp) 就是这一个区间之前所插入边的个数,我们只用删加的边。其实就是上面的还原。

    每条边最多插入 (log m) 个区间,所以遍历边时间复杂度 (mathcal O(mlog m))。并查集按秩合并是 (mathcal O(log n)) 的,总共是 (mathcal O(mlog mlog n)) 的。

    代码

    #include <map>
    #include <vector>
    #include <cstdio>
    #include <iostream>
    #define push make_pair
    using namespace std;
    typedef pair <int, int> Pair;
    
    const int N = 100005;
    
    int n, q, f[N], c[N], dep[N], s[N], tp;
    map <Pair, int> mp;
    vector <Pair> t[N << 2];
    
    int read() {
        int x = 0, f = 1; char s;
        while((s = getchar()) < '0' || s > '9') if(s == '-') f = -1;
        while(s >= '0' && s <= '9') {x = (x << 1) + (x << 3) + (s ^ 48); s = getchar();}
        return x * f;
    }
    
    int findSet(const int x) {return x == f[x] ? x : findSet(f[x]);}
    
    int dis(const int x) {return x == f[x] ? 0 : (dis(f[x]) ^ c[x]);}
    
    void unionSet(const int u, const int v, const bool flag) {
        int x = findSet(u), y = findSet(v);
        if(dep[x] < dep[y]) swap(x, y);
        if(dep[x] == dep[y]) ++ dep[x], s[++ tp] = -x;
        f[y] = x; s[++ tp] = y; c[y] = flag;
    }
    
    void Restore(const int ntp) {
        int u;
        while(tp > ntp) {
            u = s[tp]; -- tp;
            if(u > 0) f[u] = u, c[u] = 0;
            else -- dep[-u];
        }
    }
    
    void modify(const int o, const int l, const int r, const int L, const int R, const Pair p) {
        if(l > R || r < L) return;
        if(l >= L && r <= R) {t[o].push_back(p); return;}
        int mid = l + r >> 1;
        modify(o << 1, l, mid, L, R, p); modify(o << 1 | 1, mid + 1, r, L, R, p);
    }
    
    void dfs(const int o, const int l, const int r) {
        int ntp = tp;
        for(int i = 0, siz = t[o].size(); i < siz; ++ i) {
            int u = t[o][i].first, v = t[o][i].second;
            bool flag = (dis(u) ^ dis(v) ^ 1);
            if(findSet(u) == findSet(v)) {
                if(flag) {
                    for(int j = l; j <= r; ++ j) puts("NO");
                    Restore(ntp); return;
                }
            }
            else unionSet(u, v, flag);
        }
        if(l == r) {puts("YES"); Restore(ntp); return;}
        int mid = l + r >> 1;
        dfs(o << 1, l, mid); dfs(o << 1 | 1, mid + 1, r);
        Restore(ntp);
    }
    
    void makeSet() {for(int i = 1; i <= n; ++ i) f[i] = i;}
    
    int main() {
        int u, v;
        n = read(), q = read();
        makeSet();
        for(int i = 1; i <= q; ++ i) {
            u = read(), v = read();
            if(mp.count(push(u, v))) modify(1, 1, q, mp[push(u, v)], i - 1, push(u, v)), mp.erase(push(u, v));
            else mp[push(u, v)] = i;
        }
        for(map <Pair, int> :: iterator it = mp.begin(); it != mp.end(); ++ it) modify(1, 1, q, it -> second, q, it -> first);
        dfs(1, 1, q);
        return 0;
    }
    
  • 相关阅读:
    python+requests+re匹配抓取猫眼上映电影信息
    Qt 5.12 LTS 部署
    Apache 日志记录相关设置
    php curl 相关知识
    Apache缓存相关配置
    Apache开启GZIP 压缩网页
    Apache 相关 mod_rewrite ,RewriteCond,{HTTP_HOST}
    Andriod you must restart adb and eclipse
    JDK 环境变量的配置
    http 协议详解
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/12893957.html
Copyright © 2011-2022 走看看