ACM_小明滚出去?(归并排序求逆序数)

小明滚出去?

Time Limit: 2000/1000ms (Java/Others)

Problem Description:

老师:“小明,写一个排序算法”;
小明:
void mysort(int a[],int n) //n为数组a的元素个数
{
    int i,j;
    for(j=0;j< n-1;j++)
        for(i=0;i< n-1;i++)
        {
            if(a[i] >a[i+1])//数组元素大小按升序排列
            {
            	swap(a[i],a[i+1]);//交换
            }
        }
}
老师:“好,那么,问题来了,给定一个数组,按你这个算法排序,需要的交换次数是多少?回答对了今天就可以不用滚出去。”
小明按他的这个算法试了一下,发现超时了,不想天天被老师叫滚出去,小明只好求助于你,你能帮助小明今天不用滚出去么?

Input:

输入包含多组数据(EOF),每组数据第一行是一个整数n(1<=n<=10^5),第二行有n个整数(<=10^5);

Output:

对于每组数据,输出小明排序算法的交换次数。

Sample Input:

3
1 3 2
5
5 4 3 2 1
4
1 2 3 4

Sample Output:

1
10
0
解题思路:求冒泡排序的交换次数其实就是求这个序列的逆序数,归并排序水过!
AC代码:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e5+5;
 4 typedef long long LL;
 5 int n,a[maxn],tmp[maxn];LL ans;
 6 void _merge(int l,int m,int r){
 7     int i=l,j=m+1,k=l;
 8     while(i<=m&&j<=r){
 9         if(a[i]>a[j]){tmp[k++]=a[j++];ans+=(LL)m-i+1;}
10         else tmp[k++]=a[i++];
11     }
12     while(i<=m)tmp[k++]=a[i++];
13     while(j<=r)tmp[k++]=a[j++];
14     for(int i=l;i<=r;++i)a[i]=tmp[i];
15 }
16 void _merge_sort(int l,int r){
17     if(l<r){
18         int m=(l+r)>>1;
19         _merge_sort(l,m);
20         _merge_sort(m+1,r);
21         _merge(l,m,r);
22     }
23 }
24 int main(){
25     while(~scanf("%d",&n)){
26         for(int i=0;i<n;++i)scanf("%d",&a[i]);
27         ans=0;_merge_sort(0,n-1);
28         printf("%lld\n",ans);
29     }
30     return 0;
31 }

猜你喜欢

转载自www.cnblogs.com/acgoto/p/9219034.html