Description
农夫JOHN准备把他的 N(1 <= N <= 10,000)头牛排队以便于行动。因为脾气大的牛有可能会捣乱,JOHN想把牛按脾气的大小排序。每一头牛的脾气都是一个在1到100,000之间的整数并且没有两头牛的脾气值相同。在排序过程中,JOHN 可以交换任意两头牛的位置。因为脾气大的牛不好移动,JOHN需要X+Y秒来交换脾气值为X和Y的两头牛。 请帮JOHN计算把所有牛排好序的最短时间。
Input
第1行: 一个数, N。
第2~N+1行: 每行一个数,第i+1行是第i头牛的脾气值。
Output
第1行: 一个数,把所有牛排好序的最短时间。
Sample Input
3
2
3
1
输入解释:
队列里有三头牛,脾气分别为 2,3, 1。
2
3
1
输入解释:
队列里有三头牛,脾气分别为 2,3, 1。
Sample Output
7
输出解释:
2 3 1 : 初始序列
2 1 3 : 交换脾气为3和1的牛(时间=1+3=4).
输出解释:
2 3 1 : 初始序列
2 1 3 : 交换脾气为3和1的牛(时间=1+3=4).
1 2 3 : 交换脾气为1和2的牛(时间=2+1=3).
第一次写置换的题,感觉这种东西很玄学,讲不清楚qvq。
所以还是甩别人(hzwer)的题解吧->戳这里
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 const int N=1e5+10; 5 int a[N],cnt[N]; 6 using std::max; 7 using std::min; 8 bool ok[N]; 9 int read(){ 10 int ans=0,f=1;char c=getchar(); 11 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 12 while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();} 13 return ans*f; 14 } 15 int mx=0,mn=N; 16 int ans=0; 17 int main(){ 18 int n=read(); 19 for(int i=1;i<=n;i++)a[i]=read(),mx=max(mx,a[i]),mn=min(mn,a[i]),cnt[a[i]]++; 20 for(int i=mn+1;i<=mx;i++)cnt[i]+=cnt[i-1]; 21 for(int i=1;i<=n;i++){ 22 if(ok[i])continue; 23 int mni=mx,sum=0,num=0; 24 for(int j=i;;j=cnt[a[j]]){ 25 if(ok[j]){ 26 int pp=sum+mni*(num-2),pp1=sum+(num+1)*mn+mni; 27 ans+=min(pp,pp1); 28 break; 29 } 30 num++;sum+=a[j];mni=min(a[j],mni);ok[j]=1; 31 } 32 } 33 printf("%d\n",ans); 34 return 0; 35 } 36