1423H - Virus - CodeForces Solution


data structures divide and conquer dsu graphs *2500

Please click on ads to support us..

C++ Code:

// clang-format off
#include <bits/stdc++.h>
using namespace std;

// --------------------------- Defines -------------------------------------  //
template<typename A, typename B> ostream& operator<<(ostream &os, const pair<A, B> &p) { return os << '(' << p.first << ", " << p.second << ')'; }
template<
    typename T_container, typename T = typename enable_if<!is_same<T_container, string>::value, typename T_container::value_type>::type
> ostream& operator<<(ostream &os, const T_container &v) { os << '{'; string sep; for (const T &x : v) os << sep << x, sep = ", "; return os << '}'; }
void dbg_out() { cerr << endl; }
template<typename Head, typename... Tail> void dbg_out(Head H, Tail... T) { cerr << ' ' << H; dbg_out(T...); }

#ifdef FILE_STREAM
streambuf *cin_backup = cin.rdbuf(), *cout_backup = cout.rdbuf();
ifstream f_in("name.in");
ofstream f_out("name.out");
#endif // FILE_STREAM

#ifdef DEBUG
    #define dbg(...) cerr << "(" << #__VA_ARGS__ << "):", dbg_out(__VA_ARGS__)
#else
    #define dbg(...)
#endif

#define ll long long
#define fill_array(x, y) memset(x, y, sizeof(x))
#define out_range_map(x,y) ((x) < 0 || (y) < 0 || (x) == N || (y) == M)
#define sza(x) ((int)x.size())
#define all(x) (x).begin(), (x).end()
#define fori(i, N) for(int i = 0; i < N; i++)
// --------------------------- /Defines/ ------------------------------------ //

class DSURollback {
   public:
    vector<int> parent, rank;
    stack<tuple<int, int, int>> changes;
    int T = 0;

    DSURollback(){};
    DSURollback(int N) { init(N); }

    void init(int N) {
        parent.resize(N);
        rank.resize(N, 1);
        iota(parent.begin(), parent.end(), 0);
    }

    int find(int u) { return parent[u] == u ? u : find(parent[u]); }

    bool union_(int a, int b) {
        a = find(a), b = find(b);
        if (rank[a] < rank[b]) swap(a, b);
        changes.push({b, a, rank[a]});
        if (a == b) return false;
        parent[b] = a;
        rank[a] += rank[b];
        return true;
    }

    void rollback() {
        auto [b, a, ranka] = changes.top();
        changes.pop();
        parent[b] = b;
        rank[a] = ranka;
    }

    bool same_component(int u, int v) { return find(u) == find(v); }
};

class DSUQueueRollback : public DSURollback {
   private:
    typedef struct update {
        int a, b;
        char type;
    };
    vector<update> S;
    int bottom;  // bottom of the stack: S[0..bottom-1] is entirely B's

    inline void advance_bottom() {
        while (bottom < S.size() && S[bottom].type == 'B') bottom++;
    }

    void reverse_updates() {
        fori(i, S.size()) rollback();
        reverse(all(S));
        fori(i, S.size()) {
            DSURollback::union_(S[i].a, S[i].b);
            S[i].type = 'A';
        }
        bottom = 0;
    }

    void fix() {
        if (S.back().type == 'A') return;
        vector<update> saveA, saveB;

        do {
            if (S.back().type == 'A')
                saveA.push_back(S.back());
            else
                saveB.push_back(S.back());
            S.pop_back();
            rollback();
        } while (saveA.size() != saveB.size() && S.size() > bottom);
        reverse(all(saveA));
        reverse(all(saveB));
        for (const update &upd : saveB) union_(upd.a, upd.b, upd.type);
        for (const update &upd : saveA) union_(upd.a, upd.b, upd.type);
    }

   public:
    DSUQueueRollback(int N) : DSURollback(N), bottom(0) {}

    void pop() {
        assert(!S.empty());
        advance_bottom();
        if (bottom == S.size()) reverse_updates();  // No more A's
        fix();
        rollback();
        S.pop_back();
    }

    bool union_(int a, int b, char type = 'B') {
        S.push_back({a, b, type});
        return DSURollback::union_(a, b);
    }
};
// ------------------------- Your code ---------------------------------- //
// clang-format on

void Solve() {
    int n, q, k;
    cin >> n >> q >> k;
    DSUQueueRollback dsu(n + 1);

    int op, x, y, z, day = 0, day_mk = 0;
    vector<vector<pair<int, int>>> contacts(1);

    fori(i, q) {
        cin >> op;
        if (op == 1) {
            cin >> x >> y;
            contacts[day].push_back(make_pair(x, y));
            dsu.union_(x, y);
        } else if (op == 2) {
            cin >> z;
            z = dsu.find(z);
            cout << dsu.rank[z] << "\n";
        } else if (op == 3) {
            day++;
            contacts.push_back(vector<pair<int, int>>());
            if (day_mk + k == day) {
                fori(i, contacts[day_mk].size()) dsu.pop();
                day_mk++;
            }
        }
    }
}

// clang-format off
// --------------------------------------------------------------------- //

int main() {
    #ifdef DEBUG
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
    #else
        ios_base::sync_with_stdio(0); cin.tie(0);
    #endif

    int Tc = 1;
    // cin >> Tc;

    fori(i, Tc)
        Solve();

    return 0;
}


Comments

Submit
0 Comments
More Questions

237. Delete Node in a Linked List
27. Remove Element
39. Combination Sum
378. Kth Smallest Element in a Sorted Matrix
162. Find Peak Element
1529A - Eshag Loves Big Arrays
19. Remove Nth Node From End of List
925. Long Pressed Name
1051. Height Checker
695. Max Area of Island
402. Remove K Digits
97. Interleaving String
543. Diameter of Binary Tree
124. Binary Tree Maximum Path Sum
1465. Maximum Area of a Piece of Cake After Horizontal and Vertical Cuts
501A - Contest
160A- Twins
752. Open the Lock
1535A - Fair Playoff
1538F - Interesting Function
1920. Build Array from Permutation
494. Target Sum
797. All Paths From Source to Target
1547B - Alphabetical Strings
1550A - Find The Array
118B - Present from Lena
27A - Next Test
785. Is Graph Bipartite
90. Subsets II
1560A - Dislike of Threes