Description
小张在暑假时间来到工地搬砖挣钱。包工头交给他一项艰巨的任务,将一排砖头按照从低到高的顺序排好。可是小张的力量有限,每次只能交换相邻的两块砖头,请问他最少交换几次能够完成任务?
Input
第一行一个整数
,表示砖头数量。
第二行 n个整数
,表示砖头的高度。
Output
一个整数,表示最少交换几次能够完成任务。
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 | |
---|---|---|---|---|---|
测试用例 1 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
思路
本题实际上是求逆序对的个数,使用冒泡排序显然会超时。在这里用归并排序来求。在合并的时候出现a[i] > a[j](前面大于后面)即出现逆序。且由于 a[i+1] 到 a[mid] 大于 a[i] 的,它们也和 a[j] 构成逆序对。
归并排序可参看常用排序算法的C语言实现方式-优快云博客
代码
#include<stdio.h>
#include<stdlib.h>
int a[300000];
long long ans=0;
void mergesort(int left,int right)
{
if(left>=right) return;
int mid=(left+right)/2;
mergesort(left,mid);
mergesort(mid+1,right);
/*merge*/
int temp[right-left+1];
int i=left,j=mid+1,k=0;
while(i<=mid&&j<=right){
if(a[i]<=a[j])
temp[k++]=a[i++];
else{
temp[k++]=a[j++];
ans+=mid-i+1;//统计逆序数
}
}
while(i<=mid)
temp[k++]=a[i++];
while(j<=right)
temp[k++]=a[j++];
/*copy*/
for(i=left,k=0;i<=right;i++,k++)
a[i]=temp[k];
}
main()
{
int n,i,j;
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d",&a[i]);
}
mergesort(0,n-1);
printf("%lld\n",ans);
}