제출 #1139301

#제출 시각아이디문제언어결과실행 시간메모리
1139301ChottuFSirni (COCI17_sirni)C++20
0 / 140
6 ms3400 KiB
#include <bits/stdc++.h>
using namespace std;

struct DSU {
    vector<int> p, sz;
    int components; // track how many disjoint sets remain
    DSU(int n) : p(n), sz(n,1), components(n) {
        for(int i=0;i<n;i++){
            p[i] = i;
        }
    }
    int find_set(int v){
        return (p[v] == v ? v : p[v] = find_set(p[v]));
    }
    bool unite(int a,int b){
        a=find_set(a); b=find_set(b);
        if(a==b) return false;
        if(sz[a]<sz[b]) swap(a,b);
        p[b]=a; sz[a]+=sz[b];
        components--;
        return true;
    }
};

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N; 
    cin >> N;
    vector<long long> arr(N);
    for(int i=0; i<N; i++){
        cin >> arr[i];
    }

    // We only need to DSU on "card indices" [0..N-1].
    // But we also want a quick way to find "which index (or one of them) has value v".
    // pos[v] will hold all indices i s.t. arr[i] = v.
    // rep[v] = one representative index for value v, or -1 if none.
    static vector<int> pos[100001];
    for(int v=0; v<=100000; v++){
        pos[v].clear();
    }

    long long maxVal = 0;
    for(int i=0; i<N; i++){
        long long v = arr[i];
        pos[v].push_back(i);
        if(v > maxVal) maxVal = v;
    }

    // DSU structure
    DSU dsu(N);

    // 1) Unify duplicates at cost 0
    //    (If a value v appears k>1 times, unify those cards for free.)
    for(int v=1; v<=100000; v++){
        auto &indVec = pos[v];
        if(indVec.size() > 1){
            // unify them all with the first
            for(int j=1; j<(int)indVec.size(); j++){
                dsu.unite(indVec[0], indVec[j]);
            }
        }
    }

    // rep[v] = "some index whose card value == v", or -1 if none
    vector<int> rep(100001, -1);
    for(int v=1; v<=100000; v++){
        if(!pos[v].empty()){
            rep[v] = pos[v][0];
        }
    }

    // 2) For each v that appears, unify v with all multiples of v, at cost=0 if v divides those multiples exactly.
    //    We do a sieve-like pass: for m in {2v, 3v, 4v, ... up to maxVal}:
    //         if m also appears, unify rep[v], rep[m].
    //    This step merges big chunks of the graph for free.
    for(int v=1; v<=maxVal; v++){
        if(rep[v] == -1) continue;  // no card with value v
        for(long long m = 2LL*v; m <= maxVal; m += v){
            if(m <= 100000 && rep[m] != -1){
                // unify them at cost=0
                dsu.unite(rep[v], rep[m]);
            }
        }
    }

    // 3) Build edges for consecutive distinct values (in ascending order).
    //    Store them in a vector so we can Kruskal by cost.
    vector<long long> distinct;
    distinct.reserve(N); 
    for(int v=1; v<=maxVal; v++){
        if(rep[v] != -1) {
            distinct.push_back(v);
        }
    }

    sort(distinct.begin(), distinct.end()); // ascending
    vector<array<long long,3>> edges; // {cost, indexA, indexB}

    // consecutive distinct values => cost = (b % a) if a<b
    for(int i=0; i+1<(int)distinct.size(); i++){
        long long aVal = distinct[i];
        long long bVal = distinct[i+1];
        // cost:
        //   if aVal<bVal => cost = bVal % aVal ( < aVal )
        long long c = bVal % aVal;
        edges.push_back({c, rep[aVal], rep[bVal]});
    }

    // 4) Kruskal on those edges (sorted by cost).
    sort(edges.begin(), edges.end(),
         [](auto &A, auto &B){return A[0]<B[0];});

    long long ans = 0;
    for(auto &e : edges){
        long long c = e[0];
        int u = e[1], v = e[2];
        if(dsu.unite(u,v)){
            ans += c;
            // once DSU has 1 component, we can stop
            if(dsu.components==1) break;
        }
    }

    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...