ACM_逆序數(歸並排序)


幫掛科

Time Limit: 2000/1000ms (Java/Others) 64bit IO Format: %lld & %llu

Problem Description:

冬瓜發現期末很多人都掛了線代,他決定寫個程序幫掛科的同學。在一個排列中,如果一對數的前后位置與大小
順序相反,即前面的數大於后面的數,那么它們就稱為一個逆序。一個排列中逆序的總數就稱為這個排列的逆序數。
可是冬瓜想的頭發都掉光了,聰明的你肯定能夠幫幫他。

Input:

輸入有多組
第1行:N,N為序列的長度(n <= 50000)
第2 - N + 1行:序列中的元素(0 <= A[i] <= 10^9)

Output:

輸出逆序數

Sample Input:

4
2
4
3
1

Sample Output:

4
解題思路:這里用歸並排序求逆序數。主要是將序列分成兩部分,只要在有序的前半部分中找到的下標i比后半部分下標j大,那么下標i~m都可以構成逆序數對,即有(m-i+1)對,再合並子序列即可。。。
AC代碼:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=50005;
 4 int ans,n,a[N],tmp[N];//tmp是臨時數組
 5 void _merge(int l,int m,int r)//合並子序列
 6 {
 7     int i=l,j=m+1,k=l;
 8     while(i<=m && j<=r){
 9         if(a[i]>a[j]){
10             tmp[k++]=a[j++];//從小到大排列 11             ans+=m-i+1;//只要a[i]>a[j],i~m都可以構成逆序數
12         }
13         else tmp[k++]=a[i++];//相等的就直接存放到臨時數組
14     }
15     while(i<=m)tmp[k++]=a[i++];//剩余的直接拷貝
16     while(j<=r)tmp[k++]=a[j++];
17     for(int i=l;i<=r;++i)
18         a[i]=tmp[i];//臨時數組賦值給a數組
19 }
20 void _merge_sort(int l,int r)//歸並排序
21 {
22     if(l<r){
23         int m=(l+r)>>1;//分成兩部分
24         _merge_sort(l,m);//左遞歸
25         _merge_sort(m+1,r);//右遞歸
26         _merge(l,m,r);//合並兩部分
27     }
28 }
29 int main()
30 {
31     while(cin>>n){
32         for(int i=0;i<n;++i)
33             cin>>a[i];
34         ans=0;
35         _merge_sort(0,n-1);
36         cout<<ans<<endl;
37     }
38     return 0;
39 }
 
        


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM