788 逆序對的數量

2021-10-21 20:03:24 字數 2204 閱讀 9093

給定乙個長度為n的整數數列,請你計算數列中的逆序對的數量。

逆序對的定義如下:對於數列的第 i 個和第 j 個元素,如果滿足i < j 且 a[i] > a[j],則其為乙個逆序對;否則不是。

第一行包含整數n,表示數列的長度。

第二行包含 n 個整數,表示整個數列。

輸出乙個整數,表示逆序對的個數。

1≤n≤100000

623

4561

5
#include

using

namespace std;

const

int n =

1e6+10;

int q[n]

, temp[n]

;long ans;

void

merge_sort

(int q,

int l,

int r)

}//掃尾

while

(i <= mid) temp[k++

]= q[i++];

while

(j <= r) temp[k++

]= q[j++];

//把歸併後的序列複製到原序列中

for(i = l, k =

0; i <= r; i++

, k++

) q[i]

= temp[k];}

intmain()

思路:一看到這個題我就感覺似曾相識,知道需要使用歸併排序的思想來做,於是特地整理了一遍,見部落格歸併排序。

在歸併排序的歸併步驟時,可以順便統計逆序對的個數。

假設正在歸併上面的陣列,左側的2,3,6,8和右側的1,4,5,7已經排好序了,左側和右側內部都沒有逆序對,而從左側取乙個數,從右側取乙個數,則有可能形成逆序對。

例如,開始左側拿出2,右側拿出1,可知2>1,形成了逆序對。此時逆序對只是加1嗎?並不是,因為2右邊的數都是大於2的,所以可以判斷左邊的數和右邊的1可以形成4對逆序對((2,1)、(3,1)、(6,1)、(8,1))。

接下來比24,不會形成逆序對。再比34,不會形成逆序對。

當比較到64的時候,形成了逆序對,個數為2((6,4)、(8,4))。

歸納一下,也就是在歸併的時候,如果右側的元素小於左側的元素,這個時候開始統計逆序對就行了,如果左側的索引為i,左側的末尾元素的索引為mid,逆序對個數就為mid - i + 1

這樣並沒有結束,前面的假設是左側和右側是有序的,事實上並不是,左側和右側也進行了歸併的過程才能變得有序,而在歸併過程中,也能計算出逆序對的個數。

所以:總的逆序對的個數=左側歸併時求得的逆序對個數 + 右側歸併時求得的逆序對個數 + 對整體進行歸併時的逆序對個數。

可能會懷疑這三種情況會有重複,但是並沒有。左側歸併找到的逆序對相當於從左側陣列中取2個數,而整體歸併的時候是分別從左右陣列中取1個數,不可能發生重複!

思路轉至鏈結。

答案範圍:

當我們的輸入樣例是乙個降序陣列5 4 3 2 1

逆序對的數量ans

=n−1+n−2+n−3+…+1=n−1+n−2+n−3+…+1

=n∗(n−1)/2=n∗(n−1)/2

n=1e5n=1e5

ans=5e9 > int_max=1e9所以

reslong long型別

788 逆序對的數量

題目描述 給定乙個長度為n的整數數列,請你計算數列中的逆序對的數量。逆序對的定義如下 對於數列的第 i 個和第 j 個元素,如果滿足 i j 且 a i a j 則其為乙個逆序對 否則不是。輸入格式 第一行包含整數n,表示數列的長度。第二行包含 n 個整數,表示整個數列。輸出格式 輸出乙個整數,表示...

788 逆序對的數量 C

給定乙個長度為n的整數數列,請你計算數列中的逆序對的數量。逆序對的定義如下 對於數列的第 i 個和第 j 個元素,如果滿足 i j 且 a i a j 則其為乙個逆序對 否則不是。輸入格式 第一行包含整數n,表示數列的長度。第二行包含 n 個整數,表示整個數列。輸出格式 輸出乙個整數,表示逆序對的個...

ACWing 788 逆序對的數量

給定乙個長n nn的數列,計算其逆序對數量。輸入格式 第一行包含整數n nn,表示數列的長度。第二行包含n nn個整數,表示整個數列。輸出格式 輸出乙個整數,表示逆序對的個數。資料範圍 1 n 100000 1 le n le 100000 1 n 10 0000 思路是歸併排序 分治 先累加左右兩...