题意:N个高度不一的机器,排成一列,为了把他们排成高度递增的一列,每次可以交换两个机器,代价为两个机器的和
题解:
贪心+置换
1、用每个置换内部的最小值交换置换长度减一次,其他点交换一次
2、引入外部的最小点,交换它与内部最小点的位置,交换置换长度+2次后再把内部最小点换回来,其他点交换一次
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> #define ll long long using namespace std; const int N = 50010; int Mi; bool vis[N]; struct Node { int v,p; bool operator < (const Node &x) const { return v<x.v; } }a[N]; int gi() { int x=0,o=1; char ch=getchar(); while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar(); if(ch=='-') o=-1,ch=getchar(); while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); return o*x; } ll solve(int i) { int mi=a[i].v,j=a[i].p,cnt=0; ll ret=a[i].v; vis[i]=1; while(j!=i) { vis[j]=1; ret+=a[j].v; mi=min(mi,a[j].v); j=a[j].p; cnt++; } return ret+min(1ll*(cnt-1)*mi,1ll*(cnt+2)*Mi+mi); } int main() { int n=gi(); ll ans=0; for(int i=1; i<=n; i++) { a[i].v=gi(); a[i].p=i; } sort(a+1,a+n+1); Mi=a[1].v; for(int i=1; i<=n; i++) { if(!vis[i]) ans+=solve(i); } printf("%lld", ans); return 0; }