Submission #768827

# Submission time Handle Problem Language Result Execution time Memory
768827 2023-06-28T17:34:55 Z oyber Joker (BOI20_joker) C++14
0 / 100
79 ms 12296 KB
#pragma GCC optimize("O3")
#include <cstdio>
#include <vector>
#include <algorithm>
#include <functional>
#include <stack>
using namespace std;

vector<int> u;
vector<int> s;
vector<int> p;

int find(int n) {
    if (u[n] == n) return n;
    return find(u[n]);
}

int find_compress2(int n) {
    int r = n;
    int z = p[r]; 
    while (r != u[r]) {
        r = u[r];
        z ^= p[r];
    }
    while (n != r) {
        if (p[u[n]] != z) p[n] = !p[n];
        z ^= p[n];
        int next_n = u[n];
        u[n] = r;
        n = next_n;
    }
    return r;
}

int find_compress(int n) {
    if (u[n] == n) return n;
    int r = find_compress(u[n]); 
    if (p[u[n]] != p[r]) p[n] = !p[n];
    u[n] = r;
    return u[n];
}

int parity(int n) {
    if (u[n] == n) return 0;
    return parity(u[n])^p[n];
}

struct UniteInfo {
    int a;
    int b;
};

UniteInfo unite(int a, int b) {
    int ap = find(a);
    int bp = find(b);
    if (s[bp] > s[ap]) {
        swap(a, b);
        swap(ap, bp);
    }
    u[bp] = ap;
    s[ap] += s[bp];
    if (parity(a) == parity(b)) {
        p[bp] = 1;
    } else {
        p[bp] = 0;
    }
    return UniteInfo {
        ap,
        bp,
    };
}

void undo(UniteInfo info) {
    u[info.b] = info.b;
    s[info.a] -= s[info.b];
    p[info.b] = 0;
}

struct Query {
    int l;
    int r;
    int i;
};

bool comp_query(Query q1, Query q2) {
    return q1.r > q2.r;
}

bool comp_query2(Query q1, Query q2) {
    return q1.l < q2.l;
}

int main() {
    int n, m, qn;
    scanf("%d %d %d", &n, &m, &qn);

    u.resize(n);
    s.resize(n, 1);
    p.resize(n);


    vector<pair<int, int>> e(m);
    for (int i = 0; i < m; i++) {
        int a, b; 
        scanf("%d %d", &a, &b);
        a--;b--;
        e[i] = make_pair(a, b);
        //printf("%d %d %d\n", a, b, i);
    }

    vector<Query> q(qn);
    for (int i = 0; i < qn; i++) {
        int l, r;
        scanf("%d %d", &l, &r);
        l--;r--;
        q[i] = Query{l,r,i};
    }
    sort(q.begin(), q.end(), comp_query2);

    int group_size = 1024;
    int group_num = q[q.size()-1].l / group_size + 1;
    //printf("%d %d\n", int(q[q.size()-1].l), group_num);
    vector<vector<Query>> groups(group_num);
    vector<int> min_l(group_num, 1000000);
    //printf("n: %d\n", group_num);
    int j = 0;
    for (int i = 0; i < group_num; i++) {
        while (j < qn) {
            if (q[j].l >= (i+1)*group_size) break;
            groups[i].push_back(q[j]);
            min_l[i] = min(min_l[i], q[j].l);
            //printf("g: %d q: %d\n", i, q[j].i);
            j++;
        }
        sort(groups[i].begin(), groups[i].end(), comp_query);
        //printf("%d\n", min_l[i]);
    }

    vector<UniteInfo> infos;
    vector<bool> result(qn);
    for (int j = 0; j < group_num; j++) {
        if (groups[j].size() == 0) continue;;

        //reset state
        for (int i = 0; i < n; i++) {
            u[i] = i;
            s[i] = 1;
            p[i] = 0;
        }

        bool l_cycle = false;
        int current_l = 0;
        for (; current_l < min_l[j]; current_l++) {
            int a = e[current_l].first;
            int b = e[current_l].second;
            //printf("%d %d %d\n", current_l, a, b);
            //printf("(%d %d) (%d %d)\n", find_compress(a), find_compress(b), find_compress2(a), find_compress2(b));
            if (find_compress2(a) == find_compress2(b)) {
                if (parity(a) == parity(b)) {
                    l_cycle = true;
                    break;
                }
            } else {
                unite(a, b);
            }
        }
        //printf("l: %d\n", current_l);


        int current_r = m-1;
        bool r_cycle = false;
        for (int i = 0; i < int(groups[j].size()); i++) {
            if (r_cycle || l_cycle) {
                result[groups[j][i].i] = true;
                continue;
            }
            int l = groups[j][i].l;
            int r = groups[j][i].r;
            //printf("%d: %d %d\n", i, l, r);

            while (current_r > r) {
                int a = e[current_r].first;
                int b = e[current_r].second;
                //printf("%d %d %d\n", current_r, a, b);
                /*int y1 = find_compress(a); 
                int z1 = find_compress(b); 
                int y2 = find_compress2(a); 
                int z2 = find_compress2(b); 
                if (y1 != y2 || z1 != z2) {
                    printf("(%d %d) (%d %d)\n", y1, z1, y2, z2);
                }*/
                if (find_compress2(a) == find_compress2(b)) {
                    if (parity(a) == parity(b)) {
                        r_cycle = true;
                        break;
                    }
                } else {
                    unite(a, b);
                }
                current_r--;
            }

            if (r_cycle) {
                result[groups[j][i].i] = true;
                continue;
            }

            bool cycle = false;
            for (int c_l = current_l; c_l < l; c_l++) {
                int a = e[c_l].first;
                int b = e[c_l].second;
                //printf("%d %d %d\n", current_l, a, b);
                if (find(a) == find(b)) {
                    if (parity(a) == parity(b)) {
                        cycle = true;
                        break;
                    }
                } else {
                    infos.push_back(unite(a, b));
                }
            }
            if (cycle) {
                result[groups[j][i].i] = true;
            }
            while (infos.size() > 0) {
                undo(infos.back());
                infos.pop_back();
            }
        }
    }

    for (int i = 0; i < qn; i++) {
        if (result[i]) {
            printf("YES\n");
        } else {
            printf("NO\n");
        }
    }
}

Compilation message

Joker.cpp: In function 'int main()':
Joker.cpp:95:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   95 |     scanf("%d %d %d", &n, &m, &qn);
      |     ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
Joker.cpp:105:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  105 |         scanf("%d %d", &a, &b);
      |         ~~~~~^~~~~~~~~~~~~~~~~
Joker.cpp:114:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  114 |         scanf("%d %d", &l, &r);
      |         ~~~~~^~~~~~~~~~~~~~~~~
# Verdict Execution time Memory Grader output
1 Correct 1 ms 212 KB Output is correct
2 Correct 0 ms 212 KB Output is correct
3 Correct 1 ms 212 KB Output is correct
4 Correct 0 ms 288 KB Output is correct
5 Correct 0 ms 212 KB Output is correct
6 Correct 0 ms 284 KB Output is correct
7 Correct 1 ms 288 KB Output is correct
8 Incorrect 1 ms 212 KB Output isn't correct
9 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 1 ms 212 KB Output is correct
2 Correct 0 ms 212 KB Output is correct
3 Correct 1 ms 212 KB Output is correct
4 Correct 0 ms 288 KB Output is correct
5 Correct 0 ms 212 KB Output is correct
6 Correct 0 ms 284 KB Output is correct
7 Correct 1 ms 288 KB Output is correct
8 Incorrect 1 ms 212 KB Output isn't correct
9 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 1 ms 212 KB Output is correct
2 Correct 0 ms 212 KB Output is correct
3 Correct 78 ms 10992 KB Output is correct
4 Incorrect 79 ms 12296 KB Output isn't correct
5 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 1 ms 212 KB Output is correct
2 Correct 0 ms 212 KB Output is correct
3 Correct 1 ms 212 KB Output is correct
4 Correct 0 ms 288 KB Output is correct
5 Correct 0 ms 212 KB Output is correct
6 Correct 0 ms 284 KB Output is correct
7 Correct 1 ms 288 KB Output is correct
8 Incorrect 1 ms 212 KB Output isn't correct
9 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 1 ms 212 KB Output is correct
2 Correct 0 ms 212 KB Output is correct
3 Correct 1 ms 212 KB Output is correct
4 Correct 0 ms 288 KB Output is correct
5 Correct 0 ms 212 KB Output is correct
6 Correct 0 ms 284 KB Output is correct
7 Correct 1 ms 288 KB Output is correct
8 Incorrect 1 ms 212 KB Output isn't correct
9 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 1 ms 212 KB Output is correct
2 Correct 0 ms 212 KB Output is correct
3 Correct 1 ms 212 KB Output is correct
4 Correct 0 ms 288 KB Output is correct
5 Correct 0 ms 212 KB Output is correct
6 Correct 0 ms 284 KB Output is correct
7 Correct 1 ms 288 KB Output is correct
8 Incorrect 1 ms 212 KB Output isn't correct
9 Halted 0 ms 0 KB -