제출 #876447

#제출 시각아이디문제언어결과실행 시간메모리
876447tch1cherin다리 (APIO19_bridges)C++17
100 / 100
1493 ms9096 KiB
#pragma GCC optimize("Ofast,no-stack-protector") #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2") #pragma GCC optimize("unroll-loops") #pragma GCC optimize("vpt") #pragma GCC optimize("rename-registers") #pragma GCC optimize("move-loop-invariants") #pragma GCC optimize("unswitch-loops") #pragma GCC optimize(3) #pragma GCC optimize("O3") #pragma GCC optimize("inline") #pragma GCC optimize("-fgcse") #pragma GCC optimize("-fgcse-lm") #pragma GCC optimize("-fipa-sra") #pragma GCC optimize("-ftree-pre") #pragma GCC optimize("-ftree-vrp") #pragma GCC optimize("-fpeephole2") #pragma GCC optimize("-fsched-spec") #pragma GCC optimize("-falign-jumps") #pragma GCC optimize("-falign-loops") #pragma GCC optimize("-falign-labels") #pragma GCC optimize("-fdevirtualize") #pragma GCC optimize("-fcaller-saves") #pragma GCC optimize("-fcrossjumping") #pragma GCC optimize("-fthread-jumps") #pragma GCC optimize("-freorder-blocks") #pragma GCC optimize("-fschedule-insns") #pragma GCC optimize("inline-functions") #pragma GCC optimize("-ftree-tail-merge") #pragma GCC optimize("-fschedule-insns2") #pragma GCC optimize("-fstrict-aliasing") #pragma GCC optimize("-falign-functions") #pragma GCC optimize("-fcse-follow-jumps") #pragma GCC optimize("-fsched-interblock") #pragma GCC optimize("-fpartial-inlining") #pragma GCC optimize("-freorder-functions") #pragma GCC optimize("-findirect-inlining") #pragma GCC optimize("-fhoist-adjacent-loads") #pragma GCC optimize("-frerun-cse-after-loop") #pragma GCC optimize("inline-small-functions") #pragma GCC optimize("-finline-small-functions") #pragma GCC optimize("-ftree-switch-conversion") #pragma GCC optimize("-foptimize-sibling-calls") #pragma GCC optimize("-fexpensive-optimizations") #pragma GCC optimize("inline-functions-called-once") #pragma GCC optimize("-fdelete-null-pointer-checks") #include <bits/stdc++.h> using namespace std; struct dsu_save { int v, rnkv, u, rnku; dsu_save() {} dsu_save(int _v, int _rnkv, int _u, int _rnku) : v(_v), rnkv(_rnkv), u(_u), rnku(_rnku) {} }; struct dsu_with_rollbacks { vector<int> p, rnk; int comps; stack<dsu_save> op; dsu_with_rollbacks() {} dsu_with_rollbacks(int n) { p.resize(n); rnk.resize(n); for (int i = 0; i < n; i++) { p[i] = i; rnk[i] = 1; } comps = n; } int find_set(int v) { return (v == p[v]) ? v : find_set(p[v]); } bool unite(int v, int u) { v = find_set(v); u = find_set(u); if (v == u) return false; comps--; if (rnk[v] > rnk[u]) swap(v, u); op.push(dsu_save(v, rnk[v], u, rnk[u])); p[v] = u; rnk[u] += rnk[v]; return true; } void rollback() { if (op.empty()) return; dsu_save x = op.top(); op.pop(); comps++; p[x.v] = x.v; rnk[x.v] = x.rnkv; p[x.u] = x.u; rnk[x.u] = x.rnku; } }; struct edge { int from, to; int weight; }; bool operator>(edge a, edge b) { return a.weight > b.weight; } const int BLOCK = 1050; 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_with_rollbacks 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])]; rollbacks += sets.unite(from, to); } 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; rollbacks += sets.unite(edges[B].from, edges[B].to); } } answer[j] = sets.rnk[sets.find_set(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...