Submission #1353710

#TimeUsernameProblemLanguageResultExecution timeMemory
1353710po_rag526Bridges (APIO19_bridges)C++20
100 / 100
1071 ms8840 KiB
#include <bits/stdc++.h>
using namespace std;

const int B = 1000; // K�ch th??c Block chia c?n t?i ?u

// C?u tr�c c?nh
struct Edge {
    int u, v, w, id;
};

// C?u tr�c truy v?n
struct Query {
    int type, b, r, s, w, id;
};

// C?u tr�c Rollback DSU
struct DSU {
    vector<int> parent, sz;
    vector<pair<int, int>> history; // L?u l?ch s? g?p ?? Rollback

    DSU(int n) {
        parent.resize(n + 1);
        sz.resize(n + 1, 1);
        for(int i = 1; i <= n; i++) parent[i] = i;
    }

    // T�m g?c (L?u �: KH�NG d�ng n�n ???ng ?? c� th? rollback)
    int find(int i) {
        if (i == parent[i]) return i;
        return find(parent[i]); 
    }

    // G?p 2 t?p h?p (Union by Size)
    bool unite(int i, int j) {
        int root_i = find(i);
        int root_j = find(j);
        if (root_i == root_j) return false;
        
        // Lu�n g?p c�y nh? v�o c�y l?n
        if (sz[root_i] < sz[root_j]) swap(root_i, root_j);
        
        history.push_back({root_j, root_i}); // root_j tr? th�nh con c?a root_i
        parent[root_j] = root_i;
        sz[root_i] += sz[root_j];
        return true;
    }

    // L?y k�ch th??c th�nh ph?n li�n th�ng ch?a i
    int get_size(int i) {
        return sz[find(i)];
    }

    // Ho�n t�c l?i (Undo) 'steps' thao t�c g?p cu?i c�ng
    void rollback(int steps) {
        while (steps--) {
            int child = history.back().first;
            int root = history.back().second;
            history.pop_back();
            sz[root] -= sz[child]; // Tr? ?i k�ch th??c
            parent[child] = child; // C?t ??t li�n k?t
        }
    }
};

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n, m;
    if (!(cin >> n >> m)) return 0;

    vector<Edge> edges(m + 1);
    vector<int> edge_weight(m + 1); // L?u tr?ng t?i g?c c?a c�c c?nh
    for (int i = 1; i <= m; i++) {
        cin >> edges[i].u >> edges[i].v >> edges[i].w;
        edges[i].id = i;
        edge_weight[i] = edges[i].w;
    }

    int q;
    cin >> q;
    vector<Query> queries(q);
    for (int i = 0; i < q; i++) {
        cin >> queries[i].type;
        if (queries[i].type == 1) {
            cin >> queries[i].b >> queries[i].r; // Update: c?u b th�nh r
        } else {
            cin >> queries[i].s >> queries[i].w; // Query: t? s ?i xe tr?ng l??ng w
        }
        queries[i].id = i;
    }

    vector<int> ans(q, -1);
    vector<bool> changed(m + 1, false);

    // X? l� t?ng kh?i (Block) truy v?n
    for (int l = 0; l < q; l += B) {
        int r = min(q - 1, l + B - 1);
        
        vector<Query> ask_queries;
        vector<Query> update_queries;
        vector<int> changed_edges_id;

        // T�ch c�c truy v?n trong Block ra l�m 2 lo?i
        for (int i = l; i <= r; i++) {
            if (queries[i].type == 1) {
                update_queries.push_back(queries[i]);
                changed[queries[i].b] = true;
                changed_edges_id.push_back(queries[i].b);
            } else {
                ask_queries.push_back(queries[i]);
            }
        }

        // L?c c�c id c?nh b? thay ??i (x�a tr�ng l?p)
        sort(changed_edges_id.begin(), changed_edges_id.end());
        changed_edges_id.erase(unique(changed_edges_id.begin(), changed_edges_id.end()), changed_edges_id.end());

        // T?p h?p c�c c?nh KH�NG b? ??i trong block n�y
        vector<Edge> unchanged_edges;
        for (int i = 1; i <= m; i++) {
            if (!changed[i]) {
                unchanged_edges.push_back(edges[i]);
            }
        }

        // Sort truy v?n lo?i 2 gi?m d?n theo tr?ng l??ng xe
        sort(ask_queries.begin(), ask_queries.end(),[](const Query& a, const Query& b) {
            return a.w > b.w;
        });

        // Sort c?nh unchanged gi?m d?n theo tr?ng t?i
        sort(unchanged_edges.begin(), unchanged_edges.end(),[](const Edge& a, const Edge& b) {
            return a.w > b.w;
        });

        DSU dsu(n);
        int ptr = 0;

        // Duy?t t?ng truy v?n lo?i 2 ?� ???c sort
        for (auto& query : ask_queries) {
            // 1. ??a c�c c?nh UNCHANGED h?p l? v�o DSU (ch�ng s? n?m v?nh vi?n ? ?�y trong Block n�y)
            while (ptr < unchanged_edges.size() && unchanged_edges[ptr].w >= query.w) {
                dsu.unite(unchanged_edges[ptr].u, unchanged_edges[ptr].v);
                ptr++;
            }

            int rollback_steps = 0;
            
            // 2. X�t c�c c?nh CHANGED
            // ??t l?i tr?ng t?i g?c c?a c�c c?nh changed tr??c block
            for (int edge_id : changed_edges_id) {
                edges[edge_id].w = edge_weight[edge_id];
            }
            
            // C?p nh?t ?� tr?ng t?i d?a v�o c�c truy v?n Update x?y ra TR??C truy v?n hi?n t?i
            for (auto& upd : update_queries) {
                if (upd.id < query.id) {
                    edges[upd.b].w = upd.r;
                }
            }
            
            // Th�m c�c c?nh changed (n?u ?? ?i?u ki?n) v�o DSU
            for (int edge_id : changed_edges_id) {
                if (edges[edge_id].w >= query.w) {
                    if (dsu.unite(edges[edge_id].u, edges[edge_id].v)) {
                        rollback_steps++; // Ghi nh?n s? thao t�c union th�nh c�ng
                    }
                }
            }
            
            // 3. L?y ?�p �n cho truy v?n hi?n t?i
            ans[query.id] = dsu.get_size(query.s);
            
            // 4. ROLLBACK: H?y c�c c?nh changed ra kh?i DSU
            dsu.rollback(rollback_steps);
        }

        // K?t th�c block: C?p nh?t v?nh vi?n l?i m?ng g?c cho block sau
        for (auto& upd : update_queries) {
            edge_weight[upd.b] = upd.r;
            edges[upd.b].w = upd.r;
        }
        for (int edge_id : changed_edges_id) {
            changed[edge_id] = false; // Reset c?
        }
    }

    // In k?t qu? cho c�c truy v?n lo?i 2
    for (int i = 0; i < q; i++) {
        if (ans[i] != -1) {
            cout << ans[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...