QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#623055#2214. Link Cut Digraphucup-team1264AC ✓187ms28612kbC++203.9kb2024-10-09 09:53:282024-10-09 09:53:29

Judging History

你现在查看的是最新测评结果

  • [2024-10-09 09:53:29]
  • 评测
  • 测评结果:AC
  • 用时:187ms
  • 内存:28612kb
  • [2024-10-09 09:53:28]
  • 提交

answer

// https://www.youtube.com/watch?v=CrymicX875M
// Angel of mercy
// How did you move me
// Why am I on my feet again

#ifndef ONLINE_JUDGE
#include "templates/debug.hpp"
#else
#define debug(...)
#endif

#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
using u64 = uint64_t;

// #define int i64
void offlineIncrementalScc(vector<array<int, 2>> edge_updates, int n, vector<vector<int>> &joins) {
    int m = size(edge_updates);
    vector<int> ids(n, -1);
    vector<array<int, 3>> eds(m);
    for (int t = 0; t < m; t++) {
        auto [u, v] = edge_updates[t];
        eds[t] = {u, v, t};
    }
    vector<vector<int>> adj(n);
    vector<int> low(n, -1), dfn(n, -1), scc_id(n, -1);
    vector<int> stk;
    int time = 0, scc_num = 0;
    function<void(int)> tarjan = [&](int u) {
        dfn[u] = low[u] = time++;
        int sz = stk.size();
        stk.push_back(u);
        for (int v : adj[u]) {
            if (dfn[v] == -1) tarjan(v), low[u] = min(low[u], low[v]);
            else low[u] = min(low[u], dfn[v]);
        }
        if (dfn[u] == low[u]) {
            for (int i = sz; i < (int)stk.size(); i++) {
                scc_id[stk[i]] = scc_num;
                dfn[stk[i]] = n;
            }
            scc_num++;
            stk.resize(sz);
        }
    };
    auto dfs = [&](auto &&self, auto el, auto er, int tl,
                                  int tr) {
        if (tl == tr) {
            for (auto it = el; it != er; it++) {
                if (tl != -1) joins[tl].push_back(it->back());
            }
            return;
        }
        int mid = tl + (tr - tl) / 2;
        for (auto it = el; it != er; it++) {
            auto [u, v, t] = *it;
            dfn[u] = dfn[v] = -1;
            adj[u].clear(), adj[v].clear();
        }
        for (auto it = el; it != er; it++) {
            auto [u, v, t] = *it;
            if (t <= mid) adj[u].push_back(v);
        }
        time = scc_num = 0;
        for (auto it = el; it != er; it++) {
            auto [u, v, t] = *it;
            if (dfn[u] == -1) tarjan(u);
            if (dfn[v] == -1) tarjan(v);
        }
        auto split = partition(el, er, [&](const auto &ed) {
            return scc_id[ed[0]] == scc_id[ed[1]];
        });
        for (auto it = split; it != er; it++) {
            auto &[u, v, t] = *it;
            u = scc_id[u], v = scc_id[v];
        }
        self(self, el, split, tl, mid);
        self(self, split, er, mid + 1, tr);
    };
    // uses -1 as the lower bound to correctly handle self-edges
    dfs(dfs, begin(eds), end(eds), -1, m);
}

class UnionFindSet {
    vector<int> fa, sz;

  public:
    UnionFindSet(int n) : fa(n), sz(n, 1) {
        for (int i = 0; i < n; i++) {
            fa[i] = i;
        }
    }

    int size(int x) { return sz[find(x)]; }

    int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }

    int merge(int x, int y) {
        x = find(x), y = find(y);
        if (x == y) return 0;
        if (sz[x] < sz[y]) swap(x, y);
        fa[y] = x, sz[x] += sz[y];
        return 1;
    }
};

void solve() {
    int n, m; cin >> n >> m;
    vector<array<int, 2>> edge_updates(m);
    for (int i = 0; i < m; i++) {
        int u, v; cin >> u >> v;
        edge_updates[i] = {u - 1, v - 1};
    }
    vector<vector<int>> joins(m + 1);
    offlineIncrementalScc(edge_updates, n, joins);
    UnionFindSet ufs(n);
    i64 ans = 0;
    for (int t = 0; t < m; t++) {
        for (int e: joins[t]) {
            auto [u, v] = edge_updates[e];
            if (ufs.find(u) != ufs.find(v)) {
                ans += i64(ufs.size(u)) * ufs.size(v);
                ufs.merge(u, v);
            }
        }
        cout << ans << '\n';
    }
}
#undef int

// Make bold hypotheses and verify carefully
int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int t = 1;
    // cin >> t;
    while (t--) {
        solve();
    };
}

Details

Test #1:

score: 100
Accepted
time: 182ms
memory: 28612kb

Test #2:

score: 0
Accepted
time: 180ms
memory: 28360kb

Test #3:

score: 0
Accepted
time: 184ms
memory: 28568kb

Test #4:

score: 0
Accepted
time: 163ms
memory: 27724kb

Test #5:

score: 0
Accepted
time: 186ms
memory: 28456kb

Test #6:

score: 0
Accepted
time: 176ms
memory: 28544kb

Test #7:

score: 0
Accepted
time: 177ms
memory: 28328kb

Test #8:

score: 0
Accepted
time: 187ms
memory: 28316kb

Test #9:

score: 0
Accepted
time: 161ms
memory: 26816kb

Test #10:

score: 0
Accepted
time: 178ms
memory: 28520kb

Test #11:

score: 0
Accepted
time: 176ms
memory: 28244kb

Test #12:

score: 0
Accepted
time: 180ms
memory: 28496kb

Test #13:

score: 0
Accepted
time: 159ms
memory: 26740kb

Test #14:

score: 0
Accepted
time: 169ms
memory: 26460kb

Test #15:

score: 0
Accepted
time: 90ms
memory: 23772kb

Test #16:

score: 0
Accepted
time: 168ms
memory: 27112kb

Test #17:

score: 0
Accepted
time: 158ms
memory: 26980kb

Test #18:

score: 0
Accepted
time: 169ms
memory: 26900kb

Test #19:

score: 0
Accepted
time: 167ms
memory: 28436kb

Test #20:

score: 0
Accepted
time: 184ms
memory: 27296kb

Test #21:

score: 0
Accepted
time: 179ms
memory: 27472kb

Test #22:

score: 0
Accepted
time: 173ms
memory: 27584kb

Test #23:

score: 0
Accepted
time: 175ms
memory: 27492kb

Test #24:

score: 0
Accepted
time: 171ms
memory: 27488kb

Test #25:

score: 0
Accepted
time: 174ms
memory: 27400kb

Test #26:

score: 0
Accepted
time: 174ms
memory: 27332kb

Test #27:

score: 0
Accepted
time: 165ms
memory: 27416kb