Submission #947030

#TimeUsernameProblemLanguageResultExecution timeMemory
947030alextodoranSecurity Guard (JOI23_guard)C++17
100 / 100
728 ms81084 KiB
/** _ _ __ _ _ _ _ _ _ |a ||t ||o d | |o | | __ _| | _ | __| _ | | __ |/_ | __ /__\ / _\| **/ #include <bits/stdc++.h> using namespace std; typedef long long ll; const int N_MAX = 200000; const int M_MAX = 400000; int N, M, Q; int S[N_MAX + 2]; int edge_u[M_MAX + 2], edge_v[M_MAX + 2]; int order[M_MAX + 2]; int leader[N_MAX + 2]; int find_leader (int u) { return (leader[u] == 0 ? u : leader[u] = find_leader(leader[u])); } bool join (int u, int v) { u = find_leader(u); v = find_leader(v); if (u != v) { leader[u] = v; return true; } return false; } vector <int> adj[N_MAX + 2]; int root; ll cost; void init () { int mx = 0; for (int u = 1; u <= N; u++) { cost -= S[u]; mx = max(mx, S[u]); } cost += mx; root = 1; for (int u = 2; u <= N; u++) { if (S[u] < S[root]) { root = u; } } for (int u = 1; u <= N; u++) { if (u != root) { cost += S[u] + S[root]; } } } ll answer[N_MAX + 2]; struct Edge { int u, v; int delta; }; bool operator < (const Edge &e1, const Edge &e2) { return make_tuple(e1.delta, e1.u, e1.v) < make_tuple(e2.delta, e2.u, e2.v); } Edge operator - (const Edge &e, const int &val) { return Edge{e.u, e.v, e.delta - val}; } int min_comp[N_MAX + 2]; set <Edge> edges[N_MAX + 2]; set <Edge> best_edges; signed main () { ios_base::sync_with_stdio(false); cin.tie(0); cin >> N >> M >> Q; for (int u = 1; u <= N; u++) { cin >> S[u]; } for (int i = 1; i <= M; i++) { cin >> edge_u[i] >> edge_v[i]; } iota(order + 1, order + M + 1, 1); sort(order + 1, order + M + 1, [&] (const int &i, const int &j) { return S[edge_u[i]] + S[edge_v[i]] < S[edge_u[j]] + S[edge_v[j]]; }); for (int _ = 1; _ <= M; _++) { int i = order[_]; if (join(edge_u[i], edge_v[i]) == true) { adj[edge_u[i]].push_back(edge_v[i]); adj[edge_v[i]].push_back(edge_u[i]); } } init(); for (int i = N - 1; i <= Q; i++) { answer[i] = cost; } fill(leader + 1, leader + N + 1, 0); for (int u = 1; u <= N; u++) { min_comp[u] = S[u]; for (int v : adj[u]) { edges[u].insert(Edge{u, v, S[u] + S[v]}); } best_edges.insert(*edges[u].begin() - S[u]); } for (int k = N - 2; k >= 0; k--) { Edge e = *best_edges.begin(); int u = e.u, v = e.v, delta = e.delta; int U = find_leader(u), V = find_leader(v); best_edges.erase(*edges[U].begin() - min_comp[U]); best_edges.erase(*edges[V].begin() - min_comp[V]); edges[U].erase(Edge{u, v, S[u] + S[v]}); edges[V].erase(Edge{v, u, S[v] + S[u]}); cost += delta; cost -= S[root]; answer[k] = cost; if ((int) edges[U].size() > (int) edges[V].size()) { swap(U, V); } for (Edge e : edges[U]) { edges[V].insert(e); } edges[U].clear(); min_comp[V] = min(min_comp[U], min_comp[V]); leader[U] = V; best_edges.insert(*edges[V].begin() - min_comp[V]); } for (int i = 0; i <= Q; i++) { cout << answer[i] << "\n"; } return 0; }
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...