通过元素间的两两交换,把序列变成升序,每个元素都独一无二
可以看成群的置换,把现在的序列对应升序序列就是一个置换,可以看成若干个循环节
每个循环节置换的最少花费就是用循环节中最小的那个去和其他所有的交换
或者用所有数中最小的那个和循环节中最小的交换,再和循环节中其他的交换
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=1e5+1000;
int a[N],b[N],c[N];
bool vis[N];
int main()
{
int n,m=1e6;
ll ans=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
ans+=a[i];
m=min(m,a[i]);
b[i]=a[i];
c[a[i]]=i;
}
sort(b,b+n);
memset(vis,false,sizeof(vis));
for(int i=0;i<n;i++)
if(!vis[i])
{
int t=i,p=i,cnt=0;
int m0=1e6;
do
{
cnt++;
vis[t]=true;
t=c[b[t]];
m0=min(m0,a[t]);
}while(t!=p);
ans+=min((cnt-2)*m0,m0+(cnt+1)*m);
}
printf("%lld\n",ans);
return 0;
}