Submission #1279418

#TimeUsernameProblemLanguageResultExecution timeMemory
1279418uranium235Making Friends on Joitter is Fun (JOI20_joitter2)C++17
100 / 100
657 ms79976 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

struct state {
    set<int> members;
    map<int, int> inEdges;
    // ll within = 0, inSum = 0;
    void merge(state &x) {
        // assert(members.size() >= x.members.size());

        // cout << "premerge " << within << endl;

        for (int i : x.members) {
            map<int, int>::iterator it = inEdges.find(i);
            if (it != inEdges.end()) {
                // within += it->second;
                // inSum -= it->second;
                inEdges.erase(it);
            }
        }

        for (map<int, int>::iterator it = x.inEdges.begin(); it != x.inEdges.end(); it++) {
            // edge from larger to smaller
            if (members.find(it->first) != members.end()) {
                // within += it->second;                
            } else {
                inEdges[it->first] += it->second;
                // inSum += it->second;
            }
        }

        members.insert(x.members.begin(), x.members.end());
        // cout << "postmerge " << endl;
    }
    ll ans() {
        ll sz = members.size();
        return sz * (sz - 1) + inEdges.size() * sz;
    }
};

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

    int n, m;
    cin >> n >> m;
    vector<state> states(n);
    for (int i = 0; i < n; i++) states[i].members.insert(i);
    vector<int> parents(n);
    iota(parents.begin(), parents.end(), 0);

    auto par = [&](int v, auto &&self) -> int {
        return parents[v] == v ? v : (parents[v] = self(parents[v], self));
    };

    vector<set<int>> adj(n), radj(n);

    ll ans = 0;
    for (int i = 0; i < m; i++) {
        int a, b;
        cin >> a >> b;
        a--, b--;

        int ar = par(a, par), br = par(b, par);
        ans -= states[ar].ans();
        ans -= states[br].ans();
        if (ar == br) {
            // states[ar].within++;
        } else {
            states[br].inEdges[a]++;
            // states[br].inSum++;
            adj[br].insert(ar);
            radj[ar].insert(br);
        }
        ans += states[ar].ans();
        ans += states[br].ans();
        
        queue<pair<int, int>> q;
        if (adj[ar].find(br) != adj[ar].end()) q.push({ar, br});
        while (!q.empty()) {
            ar = q.front().first;
            br = q.front().second;
            ar = par(ar, par);
            br = par(br, par);
            // cout << "merging " << ar << " " << br << endl;
            q.pop();
            if (ar == br) continue;
            if (states[ar].members.size() < states[br].members.size()) swap(ar, br);
            
            ans -= states[ar].ans();
            ans -= states[br].ans();
            parents[br] = ar;
            states[ar].merge(states[br]);
            ans += states[ar].ans();

            for (int j : radj[br]) {
                set<int>::iterator it = adj[j].find(br);
                assert(it != adj[j].end());
                adj[j].erase(it);
                adj[j].insert(ar);

                if (adj[ar].find(j) != adj[ar].end() && j != ar) {
                    q.push({ar, j});
                }
            }
            for (int j : adj[br]) {
                set<int>::iterator it = radj[j].find(br);
                assert(it != radj[j].end());
                radj[j].erase(it);
                radj[j].insert(ar);

                if (radj[ar].find(j) != radj[ar].end() && j != ar) {
                    q.push({ar, j});
                }
            }
            adj[ar].insert(adj[br].begin(), adj[br].end());
            radj[ar].insert(radj[br].begin(), radj[br].end());
            adj[ar].erase(ar);
            radj[ar].erase(ar); 
        }
        // cout << "i " << i << " " << ans << endl;
        cout << ans << '\n';
        // cout << ans << endl;
    }
};  
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...