Submission #1139299

#TimeUsernameProblemLanguageResultExecution timeMemory
1139299ChottuFSirni (COCI17_sirni)C++20
0 / 140
8 ms4420 KiB
#include <bits/stdc++.h> using namespace std; struct DSU { vector<int> p, sz; DSU(int n) { p.resize(n); sz.resize(n, 1); for(int i = 0; i < n; i++){ p[i] = i; } } int find(int x) { return (p[x] == x ? x : p[x] = find(p[x])); } bool unite(int a, int b) { a = find(a); b = find(b); if(a == b) return false; if(sz[a] < sz[b]) swap(a,b); p[b] = a; sz[a] += sz[b]; return true; } }; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int N; cin >> N; vector<long long> arr(N); long long maxVal = 0; for(int i = 0; i < N; i++){ cin >> arr[i]; if(arr[i] > maxVal) maxVal = arr[i]; } // DSU for connecting the N cards themselves DSU dsu(N); // pos[v] = indices of all cards whose value is v static vector<int> pos[100001]; // since Pi <= 1e5 for(int v = 0; v <= 100000; v++){ pos[v].clear(); } for(int i = 0; i < N; i++){ pos[arr[i]].push_back(i); } // First, unite all duplicate cards of the same value at cost 0 for(int v = 1; v <= 100000; v++){ if(pos[v].size() > 1){ for(size_t i = 1; i < pos[v].size(); i++){ dsu.unite(pos[v][0], pos[v][i]); } } } // rep[v] = an index (a “representative card”) that has value v, // or -1 if v does not appear vector<int> rep(100001, -1); for(int v = 1; v <= 100000; v++){ if(!pos[v].empty()){ rep[v] = pos[v][0]; } } // Now, add zero‐cost edges where one value divides another. // For each v, if it appears, unite it with all multiples of v. // That gives cost = min(v mod m, m mod v) = 0 if v|m. for(int v = 1; v <= maxVal; v++){ if(rep[v] == -1) continue; // value v not in array // We only sieve up to maxVal for(long long mult = 2LL*v; mult <= maxVal; mult += v){ if(mult <= 100000 && rep[mult] != -1){ dsu.unite(rep[v], rep[mult]); } } } // Next, gather all *distinct* values that actually appear // (in ascending order) so we can link “neighboring” values. vector<long long> distinct; distinct.reserve(N); for(int v = 1; v <= maxVal; v++){ if(rep[v] != -1){ distinct.push_back(v); } } // Build candidate edges between consecutive distinct values. // cost = min(x % y, y % x). If x < y then cost = y % x. // We'll just do y % x for consecutive ascending x < y. vector<array<long long,3>> edges; // {cost, rep_of_x, rep_of_y} for(int i = 0; i + 1 < (int)distinct.size(); i++){ long long x = distinct[i]; long long y = distinct[i+1]; // since x < y, cost = y mod x long long c = y % x; edges.push_back({c, rep[x], rep[y]}); } // Sort these edges by cost ascending sort(edges.begin(), edges.end(), [](auto &a, auto &b){return a[0] < b[0];}); // Finally, Kruskal over those edges to connect any remaining // components. We track how many DSU components remain in the // full set of N cards. // (In principle we could track it just among the distinct reps, // but it’s simpler to count the DSU parents of all N.) long long ans = 0; // Count how many DSU "leaders" are in the entire array int compCount = 0; for(int i = 0; i < N; i++){ if(dsu.find(i) == i) compCount++; } // Kruskal: smallest edges first for(auto &e : edges){ long long c = e[0]; int a = e[1], b = e[2]; if(dsu.unite(a,b)){ ans += c; compCount--; if(compCount == 1) break; // all cards connected } } cout << ans << "\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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...