分析:
我们把序列拆成若干个轮换,一个大小为
X
X
的轮换需要次交换才能变得有序
但是这道题需要计算花费
利用贪心的思想,我们就用该轮换中的最小元素进行交换
这样其他元素只会参与一次交换,最小元素会参与
(X−1)
(
X
−
1
)
次交换
还有没有更小的交换代价呢?
我们可以用整个序列中的最小元素
minx
m
i
n
x
先于这个轮换中的最小元素
amin
a
m
i
n
交换
之后用
minx
m
i
n
x
在轮换中进行
(X−1)
(
X
−
1
)
次交换
最后再把
minx
m
i
n
x
和
amin
a
m
i
n
交换回来
那么对于每一个轮换,我们就有两种方式
选择代价较小的方案即可
在寻找轮换的时候,我们可以像查找一条链一样一路标记下去
tip
代码中我进行了离散化,但是累加的时候要加原值
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int INF=1e9;
const int N=10010;
int n,m,a[N],pos[N],V[N],minn=INF;
bool p[N];
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
minn=min(minn,a[i]);
V[i]=a[i];
}
sort(V+1,V+1+n);
for (int i=1;i<=n;i++) pos[i]=lower_bound(V+1,V+1+n,a[i])-V;
int ans=0;
for (int i=1;i<=n;i++)
if (!p[i])
{
int x=i,size=0,sum=0,mn=INF;
do
{
sum+=a[x]; size++; mn=min(mn,a[x]); p[x]=1;
x=pos[x];
}
while (x!=i);
if (size>1)
ans+=min(sum+(size+1)*minn+mn,sum+(size-2)*mn);
}
printf("%d\n",ans);
return 0;
}