Submission #997624

#TimeUsernameProblemLanguageResultExecution timeMemory
997624avighnaBridges (APIO19_bridges)C++17
13 / 100
923 ms524288 KiB
#include <bits/stdc++.h> class UFDS { public: std::vector<int> par, sz; std::vector<std::pair<int, int>> rointback; 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) { rointback.push_back({x, par[x]}); rointback.push_back({y, sz[y]}); } if (x != y) { par[x] = y; sz[y] += sz[x]; } } void rointback_previous_change() { if (!rointback.empty()) { auto p1 = rointback.back(); rointback.pop_back(); auto p2 = rointback.back(); rointback.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 = 317; struct Block { std::vector<Update> updates; std::set<int> tampered_with; std::vector<Update> in_block; // updates that happened in the block std::map<int, std::pair<int, int>> latest_val; // {value, when} UFDS dsu; Block(int n) : dsu(n) {} }; 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<Query> queries; std::vector<Block> blocks(block_size + 1, Block(n)); for (auto &b : blocks) { for (int i = 0; i < m; ++ i) { b.latest_val[i + 1] = {edges[i].d, -1}; } } for (int i = 0; i < q; ++ i) { int type; std::cin >> type; if (type == 1) { Update u; std::cin >> u.b >> u.r; u.i = i; int block_num = i / block_size; blocks[block_num].in_block.push_back(u); for (int j = block_num + 1; j <= block_size; ++ j) { blocks[j].latest_val[u.b] = {u.r, i}; } } else { Query q; std::cin >> q.s >> q.w; q.i = i; queries.push_back(q); } } for (auto &b : blocks) { for (int i = 1; i <= m; ++ i) { b.updates.push_back({b.latest_val[i].second, i, b.latest_val[i].first}); } } for (auto &b : blocks) { std::vector<Update> new_updates; for (auto &u : b.updates) { auto it = std::find_if(b.in_block.begin(), b.in_block.end(), [&u](const Update &v) { return u.b == v.b; }); if (it == b.in_block.end()) { new_updates.push_back(u); } else { b.tampered_with.insert(u.b); } } b.updates = new_updates; } for (auto &b : blocks) { std::sort(b.updates.begin(), b.updates.end(), [](Update a, Update b) { return a.r < b.r; }); std::sort(b.in_block.begin(), b.in_block.end(), [](Update a, Update b) { return a.i > b.i; }); } std::sort(queries.begin(), queries.end(), [](Query a, Query b) { return a.w > b.w; }); std::vector<int> answers(q, -1); for (auto &q : queries) { for (auto &b : blocks) { while (!b.updates.empty() && b.updates.back().r >= q.w) { int e = b.updates.back().b - 1; b.dsu.merge(edges[e].u, edges[e].v); b.updates.pop_back(); } } auto &in_block = blocks[q.i / block_size].in_block; auto &dsu = blocks[q.i / block_size].dsu; auto st = blocks[q.i / block_size].tampered_with; auto latest_val = blocks[q.i / block_size].latest_val; 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[u.b] = {u.r, u.i}; } int num_merges = 0; for (auto &b : st) { if (latest_val[b].first >= q.w) { dsu.merge(edges[b - 1].u, edges[b - 1].v, true); num_merges++; } } answers[q.i] = dsu.sz[dsu.root(q.s)]; for (int i = 0; i < num_merges; ++ i) { dsu.rointback_previous_change(); } } 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...