程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> NYOJ117 求逆序數

NYOJ117 求逆序數

編輯:C++入門知識

題目分析:
如果直接一個一個的找,時間復雜度是O(n^2),這道題數據量很大,這樣肯定會超時的。我們肯定都之後把有序數組a和b歸並成另外一個有序數組。這個思想可以用到這裡來,假設需要歸並的數據段是[Begin,Mid)和[Mid,End)。用i,j分別遍歷兩個數據段,如果後面數據段中有數據比前一個數據段中的元素小,那麼它跨越的長度就是逆序對的個數,即Mid-i,i是第一個比j大的數。這裡要注意,數組最大的元素個數是10^6,最多的逆序對的個數為10^12-10^6,int最大也就2*10^9。肯定會越界的,所以這裡要用long long來計數。

[cpp]
include<stdio.h>  
#include<string.h>  
long long Merge(int *arr, int *ans, int Begin, int Mid, int End) 

    int i,j,k; 
    long long count = 0; 
    for(i = Begin, j = Mid, k = Begin; i < Mid && j < End; ++k) 
    { 
        if(arr[i] <= arr[j]) 
            ans[k] = arr[i++]; 
        else 
        { 
            //數組2中跨越數組1的長度即為逆序對的個數  
            count += Mid - i; 
            ans[k] = arr[j++]; 
        } 
    } 
    for( ; i < Mid; ++i, ++k) 
        ans[k] = arr[i]; 
    for( ; j < End; ++j, ++k) 
        ans[k] = arr[j]; 
    memcpy(&arr[Begin], &ans[Begin], (End - Begin) * sizeof(int)); 
    return count; 

 
long long MergeSort(int *arr, int *ans, int nLen) 

    int i,l,e; 
    long long count = 0; 
    //步長跨度  
    for(l = 1; l < nLen; l *= 2) 
    { 
        for(i = 0; i + l < nLen; i += l + l) 
        { 
            //第二部分的結束  
            e = i + l + l > nLen ? nLen : i + l + l; 
            count += Merge(arr, ans, i, i + l, e); 
        } 
    } 
    return count; 

 
int arr[1000001]; 
int ans[1000001]; 
int main() 

    int i,n,t; 
    long long count; 
    scanf("%d", &t); 
    while(t--) 
    { 
        scanf("%d",&n); 
        for(i = 0; i < n; ++i) 
            scanf("%d", &arr[i]); 
        count = MergeSort(arr, ans, n); 
        printf("%lld\n", count); 
    } 
    return 0; 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved