歸併排序求逆序對

2021-10-05 13:47:16 字數 1901 閱讀 7364

輸入一串數a1,…,an,逆序對定義為滿足以下兩個條件的元組(i,j):

1 ≤i

n1≤i1≤ina

i>aj

ai>aj

ai>aj

求逆序對個數。

第一行乙個數n,第二行總共n個數,n個數可能有重複數。

其中n≤105,ai≤109。

乙個數表示逆序對個數。

思路:歸併排序合併的過程就是找出逆序對的過程,因此可以在歸併排序中加入乙個計數器。

歸併示例:

}//一組已經全部歸併

while

(i <= mid)

b[t++

]= a[i++];

while

(j <= right)

b[t++

]= a[j++];

for(i = left; i <= right; i++

) a[i]

= b[i]

;//又把資料送到原陣列

}void

mergesort

(long

long

*a,int left,

int right)

}int

main()

公升級版:

輸入乙個序列 ,交換任意兩個相鄰元素,不超過k次。交換之後,問最少的逆序對有多少個。

輸入包含多個測試。對於每個測試:第一行是n和k,?≤ ?≤ 105

10^5

105,?≤ ?≤ 109

10^9

109;第二行包括n個整數,?≤ ?_? ≤109

10^9

109最少的逆序對數量。

sample input:

3 12 2 1

3 02 2 1

sample output:12

#include

const

int maxn =

100005

;typedef

long

long ll;

ll a[maxn]

,cnt;

void

merge

(ll a[

], ll left, ll mid, ll right)

else b[t++

]=a[i++];

}while

(i <= mid)

b[t++

]=a[i++];

while

(j <= right)

b[t++

]=a[j++];

for(i=left; i<=right; i++

) a[i]

= b[i];}

void

mergesort

(ll a[

], ll left, ll right)

}int

main()

return0;

}

歸併排序求逆序對

排序都用qsort了,別的排序演算法不怎麼用,但有些排序的思想很重要。碰到一道求逆序對的題,要用到歸併排序,學習了一下歸併排序。歸併排序是用分治思想,分治模式在每一層遞迴上有三個步驟 分解 將n個元素分成個含n 2個元素的子串行。解決 用合併排序法對兩個子串行遞迴的排序。合併 合併兩個已排序的子串行...

歸併排序求逆序對

我們知道,求逆序對最典型的方法就是樹狀陣列,但是還有一種方法就是merge sort 即歸併排序。實際上歸併排序的交換次數就是這個陣列的逆序對個數,為什麼呢?我們可以這樣考慮 歸併排序是將數列a l,h 分成兩半a l,mid 和a mid 1,h 分別進行歸併排序,然後再將這兩半合併起來。在合併的...

歸併排序求逆序對

現在給定乙個有n個數的數列ai。若對於i j,有ai aj,則稱 i,j 為數列的乙個逆序對。例如,2,3,8,6,1 有五個逆序對,分別是 1,5 2,5 3,4 3,5 4,5 現在請你求出乙個給定數列的逆序對個數。輸入格式 乙個整數t,表示有多少組測試資料。每組測試資料第一行是乙個正整數n 1...