Submission #950048

#TimeUsernameProblemLanguageResultExecution timeMemory
950048efishelBridges (APIO19_bridges)C++17
100 / 100
2511 ms18332 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vll = vector <ll>;

const ll MAXN = 5E4+16, SQRT = 700;

struct Edge { ll u, v, w, id; };
struct Query { ll qu, w, id, time; };
struct Update { ll edgId, w, time; };

struct DSU { // with rollback
    stack <ll> stku, stkv;
    vll par;
    vll sz;

    DSU (ll n): par(n), sz(n, 1) {
        iota(par.begin(), par.end(), 0);
    }

    ll find (ll u) { // log(n)
        return (u == par[u] ? u : find(par[u]));
    }

    void join (ll u, ll v) { // log(n)
        u = find(u);
        v = find(v);
        if (sz[u] > sz[v]) swap(u, v); // IMPORTANT: small to large to guarantee log(n) find
        assert(sz[u] <= sz[v]);
        assert(u == par[u]);
        assert(v == par[v]);
        stku.push(u);
        stkv.push(v);
        if (u == v) return;
        // join u to v
        par[u] = v;
        sz[v] += sz[u];
    }

    void rollback () {
        assert(stku.size());
        ll u = stku.top(); stku.pop();
        ll v = stkv.top(); stkv.pop();
        if (u == v) return;
        par[u] = u;
        sz[v] -= sz[u];
    }
};

int main () {
    cin.tie(nullptr) -> sync_with_stdio(false);
    ll n, m;
    cin >> n >> m;
    vector <Edge> egs(m);
    {ll c = 0;
    for (auto &[u, v, w, id] : egs) { cin >> u >> v >> w; u--; v--; id = c++; }}
    ll Q;
    cin >> Q;
    vector <Query> qs;
    vector <Update> ups;
    vector <bool> isQry(Q);
    vll where(Q, -15);
    {ll qsid = 0;
    for (ll time = 0; time < Q; time++) {
        char type;
        cin >> type;
        switch (type) {
            case '1':
            ll edgId, newW;
            cin >> edgId >> newW;
            edgId--;
            ups.push_back({ edgId, newW, time });
            isQry[time] = false;
            where[time] = ups.size()-1;
            break;
            case '2':
            ll qu, w;
            cin >> qu >> w;
            qu--;
            qs.push_back({ qu, w, qsid, time });
            isQry[time] = true;
            where[time] = qs.size()-1;
            qsid++;
            break;
        }
    }}
    assert(*min_element(where.begin(), where.end()) != -15);
    vll vans(qs.size(), -15);
    vll upsVis(m, -16);
    for (ll i = 0; i < Q; i += SQRT) {
        vector <Query> qsblock;
        vector <Update> upsblock;
        vll involved;
        for (ll j = i; j < i+SQRT && j < Q; j++) {
            ll idx = where[j];
            if (isQry[j]) {
                qsblock.push_back(qs[idx]);
            } else {
                upsblock.push_back(ups[idx]);
                involved.push_back(ups[idx].edgId);
            }
        }
        sort(involved.begin(), involved.end());
        reverse(upsblock.begin(), upsblock.end());
        for (ll i : involved) {
            auto [u, v, w, id] = egs[i];
            upsblock.push_back({ id, w, -1 });
        }
        sort(qsblock.begin(), qsblock.end(), [&](const Query &a, const Query &b) {
            return a.w > b.w;
        });
        vector <Edge> sorted = egs;
        sort(sorted.begin(), sorted.end(), [&](const Edge &a, const Edge &b) {
            return a.w > b.w;
        });
        ll sortedi = 0;
        DSU dsu(n);
        auto addSorted = [&]() {
            auto [u, v, w, id] = sorted[sortedi];
            sortedi++;
            if (!binary_search(involved.begin(), involved.end(), id)) dsu.join(u, v);
        };
        ll toRollback = 0;
        auto addInvolved = [&](Update up, ll qtime, ll qw) {
            auto [edgId, w, time] = up;
            if (time > qtime) return; // happened later
            if (upsVis[edgId] == qtime) return; // newer version already effectuated
            upsVis[edgId] = qtime;
            auto [u, v, _, _2] = egs[edgId];
            if (qw > w) return;
            // add it
            dsu.join(u, v);
            toRollback++;
        };
        auto ans = [&](ll u) {
            return dsu.sz[dsu.find(u)];
        };
        for (auto [u, w, id, time] : qsblock) {
            while (sortedi < m && sorted[sortedi].w >= w) addSorted();
            for (Update up : upsblock) addInvolved(up, time, w); // IMPORTANT: reverse order
            vans[id] = ans(u);
            for (ll i = 0; i < toRollback; i++) dsu.rollback();
            toRollback = 0;
        }
        // prepare next block
        reverse(upsblock.begin(), upsblock.end()); // revert to original chronological order
        for (auto [edgId, w, time] : upsblock) {
            egs[edgId].w = w;
        }
    }
    assert(*min_element(vans.begin(), vans.end()) != -15);
    for (ll i : vans) cout << i << '\n';
    return 0;
}
#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...