Submission #768249

#TimeUsernameProblemLanguageResultExecution timeMemory
768249oyberJoker (BOI20_joker)C++14
71 / 100
2058 ms13068 KiB
    #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 parity(int n) {
        if (u[n] == n) return 0;
        return parity(u[n])^p[n];
    }
     
    struct UniteInfo {
        int a;
        int b;
        int sa;
    };
     
    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,
            s[ap] - s[bp],
        };
    }
     
    void undo(UniteInfo info) {
        u[info.b] = info.b;
        s[info.a] = info.sa;
        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) / group_size;
        //printf("%d %d\n", int(q[q.size()-1].l), group_num);
        vector<vector<Query>> groups(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]);
                //printf("g: %d q: %d\n", i, q[j].i);
                j++;
            }
            sort(groups[i].begin(), groups[i].end(), comp_query);
        }
     
        stack<UniteInfo> infos;
        vector<bool> result(qn);
        for (int j = 0; j < group_num; j++) {
            //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 < j*group_size; current_l++) {
                int a = e[current_l].first;
                int b = e[current_l].second;
                //printf("%d %d %d\n", current_l, a, b);
                if (find(a) == find(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);
                    if (find(a) == find(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(unite(a, b));
                    }
                }
                if (cycle) {
                    result[groups[j][i].i] = true;
                }
                while (infos.size() > 0) {
                    undo(infos.top());
                    infos.pop();
                }
            }
        }
     
        for (int i = 0; i < qn; i++) {
            if (result[i]) {
                printf("YES\n");
            } else {
                printf("NO\n");
            }
        }
    }

Compilation message (stderr)

Joker.cpp: In function 'int main()':
Joker.cpp:71:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   71 |         scanf("%d %d %d", &n, &m, &qn);
      |         ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
Joker.cpp:81:18: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   81 |             scanf("%d %d", &a, &b);
      |             ~~~~~^~~~~~~~~~~~~~~~~
Joker.cpp:90:18: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   90 |             scanf("%d %d", &l, &r);
      |             ~~~~~^~~~~~~~~~~~~~~~~
#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...