Submission #699775

#TimeUsernameProblemLanguageResultExecution timeMemory
699775badontBridges (APIO19_bridges)C++17
14 / 100
3071 ms12464 KiB
#include <iostream> #include <vector> #include <algorithm> #include <cassert> #include <cmath> #include <utility> #include <array> #include <numeric> #include <list> #include <iomanip> using namespace std; template<typename T, typename = void> struct is_iterable : false_type {}; template<typename T> struct is_iterable<T, void_t<decltype(begin(declval<T>())),decltype(end(declval<T>()))>> : true_type {}; template<typename T> typename enable_if<is_iterable<T>::value&&!is_same<T, string>::value,ostream&>::type operator<<(ostream &cout, T const &v); template<typename A, typename B> ostream& operator<<(ostream &cout, pair<A, B> const &p) { return cout << "(" << p.f << ", " << p.s << ")"; } template<typename T> typename enable_if<is_iterable<T>::value&&!is_same<T, string>::value,ostream&>::type operator<<(ostream &cout, T const &v) { cout << "["; for (auto it = v.begin(); it != v.end();) { cout << *it; if (++it != v.end()) cout << ", "; } return cout << "]"; } void dbg_out() { cout << endl; } template<typename Head, typename... Tail> void dbg_out(Head H, Tail... T) { cout << ' ' << H; dbg_out(T...); } #ifdef LOCAL #define debug(...) cout << "(" << #__VA_ARGS__ << "):", dbg_out(__VA_ARGS__) #else #define debug(...) "zzz" #endif #define all(x) x.begin(),x.end() #define pb push_back using ll = long long; using pii = pair<ll,ll>; using ld = long double; struct dsu_rollback { int n; vector<int> parent, changes, siz; dsu_rollback(int n) : n(n), parent(n), changes({}), siz(n, 1) { iota(all(parent),0); }; int find(int g) { while (g != parent[g]) g = parent[g]; return g; }; void onion(int a, int b) { a = find(a), b = find(b); if (a == b) { changes.emplace_back(-1); return; } if (siz[b] < siz[a]) swap(a, b); parent[a] = b; changes.emplace_back(a); siz[b] += siz[a]; } void rollback(int x) { /* rollback to x edges */ while ((int)changes.size() > x) { auto g = changes.back(); changes.pop_back(); if (g == -1) continue; siz[parent[g]] -= siz[g]; parent[g] = g; } } bool connected(int x, int y) { assert(x >= 0 and x < n and y >= 0 and y < n); return find(x) == find(y); } }; void solve() { ll n, m; cin >> n >> m; vector<array<ll, 3>> edges(m); for (auto& [x, y, d] : edges) { cin >> x >> y >> d; x--; y--; d = -d; } ll q; cin >> q; const int B = max(q / 2, 1LL); vector<array<ll, 3>> queries_input(q); for (auto& [T, b, r] : queries_input) { cin >> T >> b >> r; b--; r = -r; } const vector queries = queries_input; vector<ll> ans(q, -1); vector<bool> visited_query(q, false); for (ll qid = 0; qid < q; qid += B) { vector<int> process; vector<bool> changed_edges(m, false); vector<int> change_list; vector change_times(m, vector<ll>()); for (ll i = qid; i < min(qid + B, q); i++) { process.emplace_back(i); visited_query[i] = true; } for (auto query_idx : process) { auto [type, r, b] = queries[query_idx]; if (type == 1) { changed_edges[r] = true; change_times[r].pb(query_idx); change_list.pb(r); } } sort(all(change_list)); change_list.erase(unique(all(change_list)), change_list.end()); vector<int> unchanged_indices; for (int i = 0; i < m; i++) if (!changed_edges[i]) { unchanged_indices.pb(i); } sort(all(unchanged_indices), [&](int a, int b) { return edges[a][2] < edges[b][2]; }); debug(unchanged_indices); //must process all edges in --> increasing order sort(all(process), [&](int a, int b) { //if (queries[a][2] == queries[b][2]) return queries[a][0] < queries[b][0]; return queries[a][2] < queries[b][2]; }); debug(process); auto get_weight = [&](int unchanged_index) -> ll { return edges[unchanged_indices[unchanged_index]][2]; }; int unchanged_ptr = 0; dsu_rollback dsu(n); for (int i = 0; i < process.size(); i++) { int u = process[i]; auto [T, r, b] = queries[u]; while (unchanged_ptr < (int)unchanged_indices.size() and get_weight(unchanged_ptr) <= b) { auto [e1, e2, w1] = edges[unchanged_indices[unchanged_ptr]]; assert(w1 <= b); dsu.onion(e1, e2); unchanged_ptr++; } debug(u, unchanged_ptr); if (T == 1) { } else { for (auto edge_num : change_list) { assert(edge_num >= 0 and edge_num < m); auto [p1, p2, original_weight] = edges[edge_num]; ll max_less = -1; for (auto query_idx : change_times[edge_num]) if (query_idx < u) { max_less = max(max_less, query_idx); } if (max_less != -1) { auto [T2, edge_point, new_weight] = queries[max_less]; assert(T2 == 1 and edge_point == edge_num and max_less < u); if (new_weight <= b) dsu.onion(p1, p2); } else { if (original_weight <= b) dsu.onion(p1, p2); } } int parent_node = dsu.find(r); ans[u] = dsu.siz[parent_node]; } dsu.rollback(unchanged_ptr); } //update edges to be relevant for (auto query_idx : process) { auto [type, b, r] = queries[query_idx]; assert(r < 0); if (type == 1) { edges[b][2] = r; } } } for (int i = 0; i < q; i++) { int u = ans[i]; assert(visited_query[i]); if (u != -1) { assert(queries[i][0] == 2); cout << u << '\n'; } } } int main() { cin.tie(0)->sync_with_stdio(0); solve(); return 0; }

Compilation message (stderr)

bridges.cpp: In function 'void solve()':
bridges.cpp:31:20: warning: statement has no effect [-Wunused-value]
   31 | #define debug(...) "zzz"
      |                    ^~~~~
bridges.cpp:138:9: note: in expansion of macro 'debug'
  138 |         debug(unchanged_indices);
      |         ^~~~~
bridges.cpp:31:20: warning: statement has no effect [-Wunused-value]
   31 | #define debug(...) "zzz"
      |                    ^~~~~
bridges.cpp:146:9: note: in expansion of macro 'debug'
  146 |         debug(process);
      |         ^~~~~
bridges.cpp:154:27: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  154 |         for (int i = 0; i < process.size(); i++) {
      |                         ~~^~~~~~~~~~~~~~~~
bridges.cpp:31:20: warning: statement has no effect [-Wunused-value]
   31 | #define debug(...) "zzz"
      |                    ^~~~~
bridges.cpp:165:13: note: in expansion of macro 'debug'
  165 |             debug(u, unchanged_ptr);
      |             ^~~~~
#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...