Codeforces 813F Bipartite Checking 线段树 + 并查集

Bipartite Checking

感觉这种题写过很多次啦。 删边很难操作, 我们把边的影响区间丢到线段树上, 就全部变成加边了。

我们用按秩合并并查集维护每个点到根的奇偶性, 合并的时候能在小的子树的根打个标记。

#include<bits/stdc++.h>
#define LL long long
#define LD long double
#define ull unsigned long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ALL(x) (x).begin(), (x).end()
#define fio ios::sync_with_stdio(false); cin.tie(0);

using namespace std;

const int N = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1);

template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;}
template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;}
template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;}
template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;}

int n, q;
int x[N], y[N];
int fa[N], sz[N], mask[N];
bool ans[N];
vector<pair<PII, int> > event;

int getRoot(int x) {
    return fa[x] == x ? x : getRoot(fa[x]);
}

int getMask(int x, int ans) {
    ans ^= mask[x];
    if(x == fa[x]) return ans;
    return getMask(fa[x], ans);
}

void rollBack() {
    int x = event.back().fi.fi;
    int y = event.back().fi.se;
    int z = event.back().se;
    event.pop_back();
    if(x == -1) return;
    sz[x] -= sz[y];
    fa[y] = y;
    mask[y] ^= z;
}

map<PII, int> E;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1

vector<PII> Tree[N << 2];

void update(int L, int R, PII edge, int l, int r, int rt) {
    if(R < l || r < L || R < L) return;
    if(L <= l && r <= R) {
        Tree[rt].push_back(edge);
        return;
    }
    int mid = l + r >> 1;
    update(L, R, edge, lson);
    update(L, R, edge, rson);
}

void solve(bool can, int l, int r, int rt) {
    for(auto& e : Tree[rt]) {
        int u = e.fi, v = e.se;
        int x = getRoot(u);
        int y = getRoot(v);
        if(sz[x] < sz[y]) swap(x, y), swap(u, v);
        if(x == y) {
            int utox = getMask(u, 0);
            int vtoy = getMask(v, 0);
            if(!(utox ^ vtoy)) can = false;
            event.push_back(mk(mk(-1, -1), -1));
        } else {
            int utox = getMask(u, 0);
            int vtoy = getMask(v, 0);
            sz[x] += sz[y];
            mask[y] ^= (utox ^ vtoy ^ 1);
            fa[y] = x;
            event.push_back(mk(mk(x, y), (utox ^ vtoy ^ 1)));
        }
    }
    if(l == r) {
        ans[l] = can;
        for(auto& e : Tree[rt]) rollBack();
        return;
    }
    int mid = l + r >> 1;
    solve(can, lson);
    solve(can, rson);
    for(auto& e : Tree[rt]) rollBack();
}

int main() {
    for(int i = 1; i < N; i++) fa[i] = i, sz[i] = 1;
    scanf("%d%d", &n, &q);
    for(int i = 1; i <= q; i++) {
        int x, y; scanf("%d%d", &x, &y);
        if(x > y) swap(x, y);
        if(E.find(mk(x, y)) != E.end()) {
            update(E[mk(x, y)], i - 1, mk(x, y), 1, q, 1);
            E.erase(mk(x, y));
        } else {
            E[mk(x, y)] = i;
        }
    }
    for(auto& e : E) update(e.se, q, e.fi, 1, q, 1);
    E.clear();
    solve(1, 1, q, 1);
    for(int i = 1; i <= q; i++) puts(ans[i] ? "YES" : "NO");
    return 0;
}

/*
*/
原文地址:https://www.cnblogs.com/CJLHY/p/10905953.html