题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=85904#problem/A
题意:
输入n,再输入n个数a[i],以输入的顺序排列,找出相邻元素最少要交换多少次才能让所有数以从小到大的顺序排列。n为0时结束循环。
案例:
intput
5
9
1
0
5
4
0
output
6
思路分析:
n<500000,用两层循环,时间复杂度为O(n2),显然这会超时,归并排序,它的时间复杂度为O(nlogn)。所以用归并排序求解。
利用递归,把序列划分成元素个数尽可能相等的两半,直到y-x<=1,一层一层的进行判断,当右边的数小于左边的数,把右边的数的位置减去左边的数的位置,即为交换次数,再把两个数重新储存。
注意:a[i]的范围过大,要记得用long long。
源代码如下:
1 #include<iostream> 2 #define maxn 500005 3 using namespace std; 4 long long s,a[maxn],T[maxn]; 5 void merge_sort(int x,int y,long long *b,long long *t) //归并排序 6 { 7 if(y-x>1) 8 { 9 int m=x+(y-x)/2; 10 int p=x,q=m,i=x; 11 merge_sort(x,m,b,t); //左序列 12 merge_sort(m,y,b,t); //右序列 13 while(p<m||q<y) 14 { 15 if(q>=y||(p<m&&b[p]<=b[q])) t[i++]=b[p++]; 16 else 17 { 18 t[i++]=b[q++]; 19 s+=m-p; //记录交换次数 20 } 21 } 22 for(i=x;i<y;i++) b[i]=t[i]; //重新储存 23 } 24 } 25 int main() 26 { 27 int n;cin>>n; 28 while(n) 29 { 30 s=0; 31 for(int i=0;i<n;i++) 32 cin>>a[i]; 33 merge_sort(0,n,a,T); 34 cout<<s<<endl; 35 cin>>n; 36 } 37 return 0; 38 }