HDU 3743 (归并排序模板题)POJ 2299
题意:给定一个序列,然后将此序列按升序排列,每次操作只能交换相邻的两个数,求达到目标所需的最小交换次数;(ps:此题需用 long long ,否则会wa)
当然这其实就是求逆序对数;
归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
#include<stdio.h> #include<stdlib.h> #include<string.h> #define maxn 10000010 int ac[maxn],temp[maxn]; long long ans; void merger(int *A,int s,int mid,int e) { int i,j,k=0;;
//memeset(t,0,sizeof(t)); 此处不能初始化,否则会导致TLE,当然此处的初始化也是不必要的. for(i=s,j=mid+1;i<=mid && j<=e;) { if(A[i] < A[j]) temp[k++]=A[i++]; else { ans+= mid-i+1;//当a[i] > a[j]时,说明a[j]比前面那段啊[i],a[i+1],a[i+2]....,a[mid],比这些都要小,所以总逆序对数要加上mid-i+1. temp[k++]=A[j++]; } } while(i<=mid) temp[k++]=A[i++]; while(j<=e) temp[k++]=A[j++]; for(i=0;i<k;i++) A[s+i]=temp[i]; } void mergersort(int *A,int s,int e) { if(s<e) { int mid=(s+e)/2; mergersort(A,s,mid); mergersort(A,mid+1,e); merger(A,s,mid,e); } } int main() { int i,n; while(~scanf("%d",&n)) { for(i=0; i<n; i++) scanf("%d",&ac[i]); ans=0; mergersort(ac,0,n-1); printf("%lld\n",ans); } return 0; }