歸併排序求逆序對

2021-08-09 13:34:38 字數 1973 閱讀 3405

囉嗦大軍再次來襲……

#include

#include

#include

#include

#define ll long long

using

namespace

std;

const ll maxn=100000+10;

ll a[maxn],b[maxn];

ll n,total;

void msort(ll l,ll r)

//每一部分都會被分成兩部分考慮到,不用擔心逆序對個數的遺漏 如:

//3 2 1 4 6 5被分為 3 2 1 和 4 6 5 兩部分,同樣的,3 2 1 和 4 6 5 也會各自被分為3 、2 1 和 4 、6 5兩部分,

//陣列以1開頭的話,則是被分為 3 2 、1 和 4 6 、5兩部分

//以此類推 ,3 2 1 和 4 6 5這兩部分內部的逆序對也會被找出,不會產生遺漏

ll i=l,k=l,j=mid+1;//分成兩部分

while(i<=mid&&j<=r)

}while(i<=mid) b[k++]=a[i++];//j這邊的已經放完了,i那邊的還有,說明i這邊的比較大,把剩下的放進去就好 ①

while(j<=r) b[k++]=a[j++]; //同理 ②

for(ll i=l;i<=r;i++)a[i]=b[i]; //把排好序的b中的值再賦回a中 (//只更新改的這一部分 )

//把排好序(可能是部分排好序--->通過while把逆序對中小的存到大的之前,

//以前找到的逆序對消失,不會產生重複查詢的事情(乙個逆序對被多次找出並記錄的情況不會發生。))的b中的值再賦回a中,再對a

//進行查詢,重複上述操作

//另外,①與②只會出現乙個(只會有乙個滿足/成立)

}int main()

msort(1,n);

printf("%lld\n",total);

return

0;}

/*重點注意:why total+=mid-i+1

以4 5 1 6 2 3為例

我們先分析遞迴呼叫的過程,每次一分為二:

4 5 1①--->4 5②,1--->到了4,5,1遞迴就停止了...

6 2 3③--->6 2,④1--->到了6,2,1遞迴就停止了...

遞迴停止後, 開始從最後乙個遞迴呼叫返回④--->③--->②--->① 所以是先處理有半部分區間,再處理左半部分區間,也就是說,在處理 4 5 1 6 2 3

這個大區間時,左右兩個子區間都是有序的,而且是從小到大排序的,所以如果找到乙個逆序對(一定是整個區間的逆序對,所有子區間的逆序對

已經處理完了,並且小的在前,大的在後,也就是上面提到的「消失了」,最後才處理最大的原來的那個區間)因為大區間是最後處理的,

而且處理前小區間的逆序對已找出,不會有遺漏,而且兩個小區間還有序,所以上面提到的 「一定是整個區間的逆序對」的意思就是說,如果有逆序對,

也就是前乙個》後乙個,那麼這個「前乙個」一定在左區間,也就是前面的那個區間,這個「後乙個」一定在右區間,也就是後面那個區間

那便可以解釋 total+=mid-i+1的含義:

在大區間未處理之前,我們的原序列現在為:1 4 5 | 2 3 6,我們可以搜到4和2構成了一對逆序對,又因為每個區間都是遞增的,那麼,4所在的

那個區間中,在4之後的數(這裡只有5),與2肯定也能形成一堆逆序對,畢竟都比4大了,肯定比2大,所以total所加的值,也就是新找到的

逆序對的個數是包括4在內(+1)的4後面所有數的個數的總和(mid-i(i為4的座標,mid是左區間的右邊界)),所以就能得出mid-i+1來了,所以:

total+=mid-i+1

另外,各個小區間的處理方法與大區間相同,只不過是早處理一點,所以說,total+=mid-i+1也同樣適用於各個小區間

*/

有錯誤,請指出喲(^u^)ノ~

歸併排序求逆序對

排序都用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...