#include<bits/stdc++.h>
#include <algorithm>
#include <random>
#include <chrono>
#include <cstdlib>
#include <ctime>
#include <numeric>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <iomanip>
using namespace std;
#define ll long long
#define L LLONG_MAX
#define fi first
#define se second
#define pii pair<int,int>
#define sz(a) ((int)a.size())
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define REP(i,k,j) for(int i=k;i>=j;i--)
#define FORD(i,a) for(auto i:a)
#define rngdcl mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(l,r) ((l)+(rng()%(r-l+1)))
struct triple
{
int u,v,w;
};
bool operator < (triple a,triple b)
{
return a.w<b.w;
}
const int nmax=1e5+1;
const int pmax=1e7+1;
int n,mx=0;
vector<pii> p;
vector<triple> edge;
bool cnt[pmax];
void input()
{
cin >> n;
FOR(i,1,n)
{
int x; cin >> x;
if(!cnt[x]) p.push_back({x,i});
cnt[x]=true;
mx=max(mx,x);
}
}
struct DSU
{
vector<int> par;
DSU() {}
void init(int n)
{
par.resize(n+5,0);
FOR(i,1,n) par[i]=i;
}
int find(int v)
{
if(v==par[v]) return v;
return par[v]=find(par[v]);
}
bool joint(int u,int v)
{
u=find(u);
v=find(v);
if(u!=v)
{
par[v]=u;
return true;
}
return false;
}
};
DSU dsu;
// Counting sort for edges by weight (minimal extra memory: vector<int> freq of size maxw+1)
void counting_sort_edges(vector<triple>& a, int maxw)
{
if(a.empty()) return;
int K = maxw + 1;
vector<int> freq(K);
for(auto &e: a) ++freq[e.w];
for(int i=1;i<K;i++) freq[i]+=freq[i-1];
vector<triple> b(a.size());
for(int i=(int)a.size()-1;i>=0;--i)
{
int w = a[i].w;
int pos = --freq[w];
b[pos] = a[i];
}
a.swap(b);
// b freed when function exits
}
void solve()
{
dsu.init(n);
sort(p.begin(),p.end());
FORD(i,p)
{
long long cur = (long long)i.fi + 1;
while (cur <= mx)
{
auto it = lower_bound(p.begin(), p.end(), pair<int,int>((int)cur, 0));
if (it == p.end()) break;
if (it->se == i.se)
{
++it;
if (it == p.end()) break;
}
edge.push_back({ i.se, (*it).se, (*it).fi % i.fi });
long long k = (long long)(*it).fi / i.fi;
cur = (k + 1) * 1LL * i.fi;
}
}
// use counting sort instead of std::sort to avoid TLE
int maxw = 0;
for(auto &e: edge) if(e.w > maxw) maxw = e.w;
counting_sort_edges(edge, maxw);
int ans=0;
FORD(i,edge) ans+=dsu.joint(i.u,i.v)*i.w;
cout << ans;
}
int main()
{
ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
input();
solve();
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |