1. 程式人生 > >AKOJ-2021-逆序對(歸並,二分)

AKOJ-2021-逆序對(歸並,二分)

bits 組合 逆序數 數組合並 ++ return 尋找 end 排序

鏈接:https://oj.ahstu.cc/JudgeOnline/problem.php?id=2021

題意:

在一個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麽它們就稱為一個逆序。一個排列中逆序的總數就稱為這個排列的逆序數。

現在,給你一個N個元素的序列,請你判斷出它的逆序數是多少。

比如 1 3 2 的逆序數就是1。

思路:

求逆序對,之前用樹狀數組寫過,此解使用歸並排序的方法求解。

不斷對原數組進行二分,即先求解原數組左邊數組和右邊數組的逆序對數。

當對數組合並時,尋找左邊數組比右邊數組值大的數,優先處理左邊數組,即Left[i] <= Right[j]。

當兩值相等時不滿足逆序對,所以優先將左邊數組相等之加入原數組,

同時累計sum += j-1。

代碼:

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000000+10;
int Left[MAXN/2],Right[MAXN/2],a[MAXN];
int n;
long long sum = 0;
void Megre(int p,int q,int r)
{
    int w;
    for (int i = p,w = 1;i<=q;i++)
        Left[w++] = a[i];
    for (int i = q+1,w = 1;i<=r;i++)
        Right[w++] = a[i];
    int i = 1,j = 1;
    w = p;
    while (w <= r)
    {
        if (j > r-q || i <= q-p+1&&Left[i] <= Right[j])//當兩值相等時優先處理左邊數組
        {
            a[w] = Left[i];
            i++;
            sum += j-1;//右邊數組往後移動位數即右邊比左邊當前位置值小的值個數
        }
        else
        {
            a[w] = Right[j];
            j++;
            //sum += i-1;
        }
        w++;
    }
}

void Megre_sort(int p,int r)
{
    if (p < r)
    {
        int q = (p + r) / 2;
        Megre_sort(p, q);
        Megre_sort(q + 1, r);
        Megre(p, q, r);
        /*
        cout << p << ‘ ‘ << r << ‘:‘ << endl;
        cout << sum << endl;
         */
    }
}

int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        cin >> n;
        for (int i = 1;i<=n;i++)
            cin >> a[i];
        sum = 0;
        Megre_sort(1,n);
        cout << sum << endl;
    }

    return 0;
}

  

AKOJ-2021-逆序對(歸並,二分)