kyopro_library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub dyktr06/kyopro_library

:heavy_check_mark: test/yukicoder/yuki_416.test.cpp

Depends on

Code

#define PROBLEM "https://yukicoder.me/problems/no/416"
#include <iostream>
#include <vector>
#include <set>

#include "../../lib/data_structure/partly_persistent_union_find.hpp"

using namespace std;

int main(){
    int n, m, q; cin >> n >> m >> q;
    PersistentUnionFind tree(n);
    vector<pair<int, int>> p1, p2;
    set<pair<int, int>> s;
    for(int i = 0; i < m; i++){
        int a, b; cin >> a >> b; a--; b--;
        p1.emplace_back(a, b);
    }
    for(int i = 0; i < q; i++){
        int c, d; cin >> c >> d; c--; d--;
        p2.emplace_back(c, d);
        s.insert({c, d});
    }
    for(int i = 0; i < m; i++){
        auto [a, b] = p1[i];
        if(s.find({a, b}) == s.end()){
            tree.unite(a, b);
        }
    }
    for(int i = q - 1; i >= 0; i--){
        auto [a, b] = p2[i];
        tree.unite(a, b);
    }
    for(int i = 1; i < n; i++){
        if(!tree.same(0, i, m)){
            cout << 0 << "\n";
            continue;
        }else if(tree.same(0, i, m - q)){
            cout << -1 << "\n";
            continue;
        }
        int ok = m, ng = m - q;
        while(abs(ok - ng) > 1){
            int mid = (ok + ng) / 2;
            if(tree.same(0, i, mid)){
                ok = mid;
            }else{
                ng = mid;
            }
        }
        cout << m - ok + 1 << "\n";
    }
}
#line 1 "test/yukicoder/yuki_416.test.cpp"
#define PROBLEM "https://yukicoder.me/problems/no/416"
#include <iostream>
#include <vector>
#include <set>

#line 2 "lib/data_structure/partly_persistent_union_find.hpp"

/**
 * @brief Partly Persistent Union-Find
 * @docs docs/data_structure/partly_persistent_union_find.md
 */

#line 9 "lib/data_structure/partly_persistent_union_find.hpp"
#include <algorithm>

struct PersistentUnionFind{
    int now;
    std::vector<int> par, rank, time;
    std::vector<std::vector<std::pair<int, int>>> num;
    const int INF = 1 << 30;

    PersistentUnionFind(const int N) : par(N), rank(N), time(N), num(N){
        now = 0;
        for(int i = 0; i < N; ++i){
            par[i] = i;
            num[i].emplace_back(0, 1);
        }
        std::fill(rank.begin(), rank.begin() + N, 0);
        std::fill(time.begin(), time.begin() + N, INF);
    }

    int root(const int x, const int t){
        if(t < time[x]) return x;
        return root(par[x], t);
    }

    void unite(const int x, const int y){
        ++now;

        int rx = root(x, now);
        int ry = root(y, now);
        if(rx == ry) return;

        if(rank[rx] < rank[ry]) std::swap(rx, ry);
        num[rx].emplace_back(now, size(rx, now) + size(ry, now));

        par[ry] = rx;
        time[ry] = now;
        if(rank[rx] == rank[ry]) ++rank[rx];
    }

    bool same(const int x, const int y, const int t){
        int rx = root(x, t);
        int ry = root(y, t);
        return rx == ry;
    }

    int size(const int x, const int t){
        int rx = root(x, t);

        int ok = 0, ng = num[rx].size();
        while(abs(ok - ng) > 1){
            int mid = (ok + ng) / 2;
            if(num[rx][mid].first <= t){
                ok = mid;
            } else{
                ng = mid;
            }
        }
        return num[rx][ok].second;
    }
};
#line 7 "test/yukicoder/yuki_416.test.cpp"

using namespace std;

int main(){
    int n, m, q; cin >> n >> m >> q;
    PersistentUnionFind tree(n);
    vector<pair<int, int>> p1, p2;
    set<pair<int, int>> s;
    for(int i = 0; i < m; i++){
        int a, b; cin >> a >> b; a--; b--;
        p1.emplace_back(a, b);
    }
    for(int i = 0; i < q; i++){
        int c, d; cin >> c >> d; c--; d--;
        p2.emplace_back(c, d);
        s.insert({c, d});
    }
    for(int i = 0; i < m; i++){
        auto [a, b] = p1[i];
        if(s.find({a, b}) == s.end()){
            tree.unite(a, b);
        }
    }
    for(int i = q - 1; i >= 0; i--){
        auto [a, b] = p2[i];
        tree.unite(a, b);
    }
    for(int i = 1; i < n; i++){
        if(!tree.same(0, i, m)){
            cout << 0 << "\n";
            continue;
        }else if(tree.same(0, i, m - q)){
            cout << -1 << "\n";
            continue;
        }
        int ok = m, ng = m - q;
        while(abs(ok - ng) > 1){
            int mid = (ok + ng) / 2;
            if(tree.same(0, i, mid)){
                ok = mid;
            }else{
                ng = mid;
            }
        }
        cout << m - ok + 1 << "\n";
    }
}
Back to top page