[51nod1125]交换机器的最小代价
设每个数最终的位置是$p_i$, 每个数当前的位置是$i$, 由于数是独一无二的, 所以pi - i是一一映射的关系
然后我们让$i -> p_i$, 建立一个图
那么, 考虑一个环, 我们可以让最小的值沿着来边走一$n-1$步($n$是环的大小), 亦或是让最小值和全局最小值交换一下, 让全局最小值来代替他走一圈, 再把全局最小值交换回去
(感觉显然是对的)
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; #define pb push_back #define ln '\n' const int N = 2e5+5; const int mod = 998244353; inline void inc(int &a, int b){ a+=b; if(a>=mod) a-=mod; } inline void dec(int &a, int b){ a-=b; if(a<0) a+=mod; } int n, p[N], f[N], mn[N], siz[N]; int find(int x){return f[x]==x?x:f[x]=find(f[x]);} ll sum[N]; int main(){ ios::sync_with_stdio(false); cin.tie(0); cin >> n; vector<int> b; for(int i=1; i<=n; i++) cin >> p[i], b.pb(p[i]); sort(b.begin(), b.end()); for(int i=1; i<=n; i++) p[i] = lower_bound(b.begin(), b.end(), p[i])-b.begin() + 1; for(int i=1; i<=n; i++) f[i] = i, sum[i] = mn[i] = b[p[i]-1], siz[i] = 1; for(int i=1; i<=n; i++){ int fx = find(i), fy = find(p[i]); if(fx != fy){ f[fy] = fx; sum[fx] += sum[fy]; mn[fx] = min(mn[fx], mn[fy]); siz[fx] += siz[fy]; } } ll ans = 0; for(int i=1; i<=n; i++) if(f[i] == i){ ll tmp1 = sum[i] - mn[i] + 1ll * mn[i] * (siz[i]-1); ll tmp2 = sum[i] - mn[i] + 1ll * b[0] * (siz[i]-1) + (b[0]+mn[i])*2; //把1跟最小值换一下, 然后让1走一圈, 然后换回来 ans = ans + min(tmp1, tmp2); } cout << ans << ln; }