제출 #1141420

#제출 시각아이디문제언어결과실행 시간메모리
1141420anmattroiJoker (BOI20_joker)C++17
100 / 100
495 ms11372 KiB
/********************************************

Task: BalticOI20_Joker
Link: https://oj.uz/problem/view/BOI20_joker

********************************************/

#include <bits/stdc++.h>
#define maxn 200005
#define fi first
#define se second
using namespace std;
using ii = pair<int, int>;

constexpr int B = 100;

int n, m, q;
ii edge[maxn];

int rk[maxn];
ii par[maxn];
bool graph_is_bipartite = true;

int last[maxn];
bool nho[maxn];

vector<tuple<int, int, int, int, int> > Stack;

void rollback() {
    assert(!Stack.empty());
    auto [u, rku, v, rkv, state] = Stack.back(); Stack.pop_back();
    par[u] = {u, 0};
    par[v] = {v, 0};
    rk[u] = rku;
    rk[v] = rkv;
    graph_is_bipartite = state;
}

ii find_set(int v) {
    if (v == par[v].fi) return ii{v, 0};
    ii tr = find_set(par[v].fi);
    return ii{tr.fi, tr.se^par[v].se};
}


bool union_set(int u, int v) {
    ii tu = find_set(u), tv = find_set(v);
    int a = tu.fi, b = tv.fi;
    if (tu.fi == tv.fi) {
        if (tu.se == tv.se) {
            Stack.emplace_back(a, rk[a], b, rk[b], graph_is_bipartite);
            graph_is_bipartite = false;
            return true;
        }
        return false;
    }

    if (rk[a] > rk[b]) swap(a, b);
    Stack.emplace_back(a, rk[a], b, rk[b], graph_is_bipartite);
    par[a] = {b, tu.se^tv.se^1};
    rk[b] += rk[a] == rk[b];
    return true;
}



void solve(int l1 = 1, int l2 = m, int r1 = 1, int r2 = m) {
    int mid = (l1 + l2) / 2;
    for (int i = l1; i <= mid; i++) nho[i] = union_set(edge[i].fi, edge[i].se);
    last[mid] = r1;
    for (int i = r2; i >= r1; i--) {
        nho[i] = union_set(edge[i].fi, edge[i].se);
        if (!graph_is_bipartite) {
            last[mid] = i+1;
            break;
        }
    }
    assert(last[mid]);
    for (int i = last[mid]-1; i <= r2; i++) if (nho[i]) rollback();
    for (int i = mid; i >= l1; i--) if (nho[i]) rollback();

    for (int i = last[mid]+1; i <= r2; i++) nho[i] = union_set(edge[i].fi, edge[i].se);
    if (l1 < mid) solve(l1, mid-1, r1, last[mid]);

    for (int i = last[mid]+1; i <= r2; i++) if (nho[i]) rollback();


    for (int i = l1; i <= mid; i++) nho[i] = union_set(edge[i].fi, edge[i].se);
    if (mid < l2) solve(mid+1, l2, last[mid]-1, r2);
    for (int i = l1; i <= mid; i++) if (nho[i]) rollback();

}

void sub0() {
    for (int i = 1; i <= m; i++) union_set(edge[i].fi, edge[i].se);
    if (graph_is_bipartite) {
        while (q--) {
            int l, r;
            cin >> l >> r;
            cout << "NO\n";
        }
        exit(0);
    }
    while (!Stack.empty()) rollback();
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n >> m >> q;
    for (int i = 1; i <= m; i++) cin >> edge[i].fi >> edge[i].se;
    for (int i = 1; i <= n; i++) par[i] = {i, 0};

    sub0();

    int p = m;
    union_set(edge[m].fi, edge[m].se);
    for (int i = 1; i <= m; i++) {
        union_set(edge[i].fi, edge[i].se);
        if (!graph_is_bipartite) {
            p = i-1;
            break;
        }
    }

    cerr << p << "\n";

    for (int i = p+1; i <= m; i++) last[i] = m+1;
    while (!Stack.empty()) rollback();


    solve(1, p, 1, m);
    while (!Stack.empty()) rollback();

    p = m+1;
    for (int i = 1; i <= m; i++) {
        union_set(edge[i].fi, edge[i].se);
        if (!graph_is_bipartite) {
            p = i;
            break;
        }
    }
    while (!Stack.empty()) rollback();
    for (int i = p; i <= m; i++) last[i] = m+2;
    cerr << p << "\n";
    last[0] = m+2;
    for (int i = m; i >= 1; i--) {
        union_set(edge[i].fi, edge[i].se);
        if (!graph_is_bipartite) {
            last[0] = i+1;
            break;
        }
    }
    for (int i = 0; i < m; i++) cerr << last[i] << ' '; cerr << "\n";
    while (q--) {
        int l, r;
        cin >> l >> r;
        cout << (r+1 >= last[l-1] ? "NO\n" : "YES\n");
    }

}
/*
3 3 6
1 2
2 3
3 1
1 1
1 2
1 3
2 2
2 3
3 3
*/
/*
YES
YES
YES
YES
YES
YES
*/
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...