Submission #997738

#TimeUsernameProblemLanguageResultExecution timeMemory
997738avighnaBridges (APIO19_bridges)C++17
27 / 100
3032 ms12196 KiB
#include <bits/stdc++.h>

class UFDS {
public:
    std::vector<int> par, sz;
    std::vector<std::pair<int, int>> rollback;

    UFDS(int n) : par(n + 1), sz(n + 1, 1) {
        std::iota(par.begin(), par.end(), 0);
    }

    int root(int x) {
        return x == par[x] ? x : root(par[x]);
    }

    void merge(int x, int y, bool should_rointback = false) {
        x = root(x);
        y = root(y);
        if (sz[x] > sz[y]) {
            std::swap(x, y);
        }
        if (should_rointback) {
            rollback.push_back({x, par[x]});
            rollback.push_back({y, sz[y]});
        }
        if (x != y) {
            par[x] = y;
            sz[y] += sz[x];
        }
    }

    void rollback_all_changes() {
        while (!rollback.empty()) {
            auto p1 = rollback.back();
            rollback.pop_back();
            auto p2 = rollback.back();
            rollback.pop_back();
            sz[p1.first] = p1.second;
            par[p2.first] = p2.second;
        }
    }
};

struct Edge {
    int u, v, d;
};

struct Update {
    int i;
    int b, r;
};

struct Query {
    int i;
    int w, s;
};

const int block_size = 5000;
struct Block {
    std::vector<Query> queries;
    std::vector<Update> in_block; // updates that happened in the block
    std::set<int> in_b;
};

class map_with_rollbacks {
public:
    std::map<int, std::pair<int, int>> m;

    std::vector<std::pair<int, int>> rollback;

    void modify(int x, std::pair<int, int> y, bool should_rollback = false) {
        if (should_rollback) {
            rollback.push_back({x, x});
            rollback.push_back(m[x]);
        }
        m[x] = y;
    }

    void rollback_all_changes() {
        while (!rollback.empty()) {
            auto p1 = rollback.back();
            rollback.pop_back();
            auto p2 = rollback.back();
            rollback.pop_back();
            m[p2.first] = p1;
        }
    }
};

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

    int n, m;
    std::cin >> n >> m;
    std::vector<Edge> edges(m);
    for (auto &edge : edges) {
        std::cin >> edge.u >> edge.v >> edge.d;
    }
    int q;
    std::cin >> q;
    std::vector<Block> blocks(std::ceil(double(q) / block_size));
    for (int i = 0; i < q; ++ i) {
        int type;
        std::cin >> type;
        int block_num = i / block_size;
        if (type == 1) {
            Update u;
            std::cin >> u.b >> u.r;
            u.i = i;
            blocks[block_num].in_block.push_back(u);
            blocks[block_num].in_b.insert(u.b);
        } else {
            Query q;
            std::cin >> q.s >> q.w;
            q.i = i;
            blocks[block_num].queries.push_back(q);
        }
    }
    for (auto &b : blocks) {
        std::sort(b.in_block.begin(), b.in_block.end(), [](Update a, Update b) { return a.i > b.i; });
        std::sort(b.queries.begin(), b.queries.end(), [](Query a, Query b) { return a.w > b.w; });
    }

    std::vector<int> answers(q, -1);
    map_with_rollbacks latest_val; // {value, updated when}
    for (int i = 0; i < m; ++ i) {
        latest_val.modify(i + 1, {edges[i].d, -1});
    }
    for (auto &b : blocks) {
        std::vector<Update> updates;
        std::set<int> st;
        for (int i = 1; i <= m; ++ i) {
            Update u = {latest_val.m[i].second, i, latest_val.m[i].first};
            if (b.in_b.count(u.b)) {
                st.insert(u.b);
            } else {
                updates.push_back(u);
            }
        }
        std::sort(updates.begin(), updates.end(), [](Update a, Update b) { return a.r < b.r; });
        UFDS dsu(n);
        for (auto &q : b.queries) {
            while (!updates.empty() && updates.back().r >= q.w) {
                int e = updates.back().b - 1;
                dsu.merge(edges[e].u, edges[e].v);
                updates.pop_back();
            }
            auto &in_block = blocks[q.i / block_size].in_block;
            std::set<int> enc;
            for (auto &u : in_block) {
                if (u.i > q.i) {
                    continue;
                }
                if (enc.count(u.b)) {
                    continue;
                }
                enc.insert(u.b);
                latest_val.modify(u.b, {u.r, u.i}, true);
            }
            for (auto &b : st) {
                if (latest_val.m[b].first >= q.w) {
                    dsu.merge(edges[b - 1].u, edges[b - 1].v, true);
                }
            }
            answers[q.i] = dsu.sz[dsu.root(q.s)];
            dsu.rollback_all_changes();
            latest_val.rollback_all_changes();
        }
        std::set<int> enc;
        for (auto &u : b.in_block) {
            if (enc.count(u.b)) {
                continue;
            }
            enc.insert(u.b);
            latest_val.m[u.b] = {u.r, u.i};
        }
    }

    for (auto &i : answers) {
        if (i != -1) {
            std::cout << i << "\n";
        }
    }
}
#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...