還是火柴排隊(補一下歸併排序的鍋)

2022-05-16 04:32:32 字數 1520 閱讀 5812

原文章傳送門

好吧,我們上次說這道題可以用歸併排序做。。

但是我不會歸併排序的鍋(真是蒟蒻。。)

早晨爬起來趕緊學一發。。

貌似還挺簡單的。。

233~

好吧,切入正題。

歸併排序其實就是利用了分治的思想。

分治:將乙個大問題分為2個小問題,之後解決所有的小問題,再合併答案。

比如我們舉乙個數列,對它進行歸併排序。

a[10]=

歸併的順序是這樣的;;

分到這一步後,有2種方法:

第一是繼續分,然後歸併,第二是不分,然後判斷一下2個數的大小關係,如變為然後歸併。。(其實複雜度差不多,就是少幾個常數。。)

合併過程:(接上表)

恩,就是這樣。

合併的**實現就是將2塊陣列放2個指標。

逐一掃瞄,比較。

然後把結果重新放回原陣列中

好吧,感覺講的不是很清楚。

然後逆序對的個數呢,是這樣的;

在歸併排序中

假設我們要合併2個有序的數列a1,a2

那麼假設a1中left<=i<=mid 

a2中mid如果a1[i]>=a2[j]

那麼a1[k](i<=k<=mid)一定》a2[j]

所以逆序對(也就是ans)+=mid-i+1;(+1是因為包括i本身也是逆序對)

還是上**吧。。

#include#include

#include

#define mod 99999997

using

namespace

std;

struct

lisana[

100001],b[100001

];int result[100001],c[100001],d[100001

],ans,n;

bool cmp(lisan a,lisan b)

void mergesort(int left,int

right)

while(i<=mid)

d[k++]=c[i++];

while(j<=right)

d[k++]=c[j++];

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

c[i]=d[i];

}int

main()

for(int i=1;i<=n;i++)

sort(a+1,a+n+1

,cmp);

sort(b+1,b+n+1

,cmp);

for(int i=1;i<=n;i++)

c[b[i].opt]=a[i].opt;

mergesort(

1,n);

printf("%d

",ans);

}

比樹狀陣列快誒。(樹狀陣列背鍋。。)

其實都是o(nlogn)只不過常數小了點。

恩,就是這樣。

線段樹演算法和亂七八糟的演算法還是去死吧。。(等我成為蒟蒻中的巨神再回來補。。)

NOIP2013 火柴排隊(歸併排序)

涵涵有兩盒火柴,每盒裝有 n 根火柴,每根火柴都有乙個高度。現在將每盒中的火柴各自排成一列,同一列火柴的高度互不相同,兩列火柴之間的距離定義為 ai bi 2 其中 ai 表示第一列火柴中第 i 個火柴的高度,bi 表示第二列火柴中第 i 個火柴的高度。每列火柴中相鄰兩根火柴的位置都可以交換,請你通...

PTA 7 18 銀行排隊模擬(歸併排序的應用)

這個題是歸併排序的乙個簡單應用,只需要掌握好歸併排序的思想,很容易寫出。設某銀行有a b兩個業務視窗,且處理業務的速度不一樣,其中a視窗處理速度是b視窗的2倍 即當a視窗每處理完2個顧客時,b視窗處理完1個顧客。給定到達銀行的顧客序列,請按業務完成的順序輸出顧客序列。假定不考慮顧客先後到達的時間間隔...

C 下的歸併排序演算法實現

發現自己演算法的功底很差 這幾天看mit的演算法導論課程 學習了一下歸併演算法 下面為 總體上不算是簡介 尤其是拆陣列的部分 其實可以是可以不拆直接在原陣列上面操作的 但是由於歸併部分的介面設計成了兩個陣列為引數 所以說不得不這樣子例項化兩個陣列了 當然歸併部分也可以直接寫到排序裡面 應該可以省下很...