給定乙個長度為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))。
接下來比2
和4
,不會形成逆序對。再比3
和4
,不會形成逆序對。
當比較到6
和4
的時候,形成了逆序對,個數為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
所以
res
為long 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 思路是歸併排序 分治 先累加左右兩...