Submission #849231

#TimeUsernameProblemLanguageResultExecution timeMemory
849231tch1cherinBridges (APIO19_bridges)C++17
59 / 100
3041 ms10404 KiB
#pragma GCC optimize("Ofast,unroll-loops") #pragma GCC target("avx2") #include <bits/stdc++.h> using namespace std; struct dsu { vector<int> parent, rank; vector<vector<pair<int*, int>>> changes; dsu(int size) : parent(size), rank(size, 1) { iota(parent.begin(), parent.end(), 0); } int get(int u) { return parent[u] == u ? u : get(parent[u]); } void unite(int u, int v) { u = get(u), v = get(v); changes.push_back({}); if (u != v) { if (rank[u] < rank[v]) { swap(u, v); } changes.back().reserve(2); changes.back().push_back({&rank[u], rank[u]}); changes.back().push_back({&parent[v], parent[v]}); rank[u] += rank[v]; parent[v] = u; } } void rollback() { for (auto &[x, y] : changes.back()) { *x = y; } changes.pop_back(); } }; struct edge { int from, to; int weight; }; bool operator>(edge a, edge b) { return a.weight > b.weight; } const int BLOCK = 500; int main() { cin.tie(nullptr)->sync_with_stdio(false); int N, M; cin >> N >> M; vector<edge> edges(M); for (auto &[from, to, weight] : edges) { cin >> from >> to >> weight; from--, to--; } int Q; cin >> Q; vector<int> answer(Q, -1); vector<tuple<int, int, int>> changes, queries; vector<bool> is_changed(M), used(M); for (int i = 0; i < Q; i++) { int T; cin >> T; if (T == 1) { int B, R; cin >> B >> R; B--; is_changed[B] = true; changes.push_back({i, B, R}); } else { int S, W; cin >> S >> W; S--; queries.push_back({i, S, W}); } if ((Q - i - 1) % BLOCK == 0) { vector<pair<edge, int>> sorted_edges(M); for (int i = 0; i < M; i++) { sorted_edges[i] = {edges[i], i}; } sort(sorted_edges.begin(), sorted_edges.end(), [](pair<edge, int>& a, pair<edge, int>& b) { return a.first > b.first; }); sort(queries.begin(), queries.end(), [](tuple<int, int, int> a, tuple<int, int, int> b) { return get<2>(a) > get<2>(b); }); int ptr = 0; dsu sets(N); for (auto [j, S, W] : queries) { while (ptr < M && sorted_edges[ptr].first.weight >= W) { if (!is_changed[sorted_edges[ptr].second]) { sets.unite(sorted_edges[ptr].first.from, sorted_edges[ptr].first.to); } ptr++; } int x = (int)changes.size(); for (int k = 0; k < (int)changes.size(); k++) { if (get<0>(changes[k]) > j) { x = k; break; } } int rollbacks = 0; for (int k = x - 1; k >= 0; k--) { if (!used[get<1>(changes[k])] && get<2>(changes[k]) >= W) { auto [from, to, weight] = edges[get<1>(changes[k])]; sets.unite(from, to); rollbacks++; } used[get<1>(changes[k])] = true; } for (int k = (int)changes.size() - 1; k >= x; k--) { auto [y, B, R] = changes[k]; if (!used[B] && edges[B].weight >= W) { used[B] = true; sets.unite(edges[B].from, edges[B].to); rollbacks++; } } answer[j] = sets.rank[sets.get(S)]; for (int k = (int)changes.size() - 1; k >= 0; k--) { used[get<1>(changes[k])] = false; } for (int k = 0; k < rollbacks; k++) { sets.rollback(); } } for (auto [j, B, R] : changes) { is_changed[B] = false; edges[B].weight = R; } vector<tuple<int, int, int>>().swap(changes); vector<tuple<int, int, int>>().swap(queries); } } for (int i = 0; i < Q; i++) { if (answer[i] != -1) { cout << answer[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...