原文章傳送門
好吧,我們上次說這道題可以用歸併排序做。。
但是我不會歸併排序的鍋(真是蒟蒻。。)
早晨爬起來趕緊學一發。。
貌似還挺簡單的。。
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的演算法導論課程 學習了一下歸併演算法 下面為 總體上不算是簡介 尤其是拆陣列的部分 其實可以是可以不拆直接在原陣列上面操作的 但是由於歸併部分的介面設計成了兩個陣列為引數 所以說不得不這樣子例項化兩個陣列了 當然歸併部分也可以直接寫到排序裡面 應該可以省下很...