歸併排序
《算導》p20:分治法中的遞迴式是基於基本模式中的三個步驟的。如先前一樣,設t(n)為乙個規模為n的問題的執行時間。如果問題的規模足夠地小,如n≤c(c為乙個常量),則得到它的直接解的時間為常量,寫作θ(1)。假設我們把原問題分解成a個子問題,每乙個的大小是原問題的1/b。(對於合併排序,a和b都是2,但在許多分治法中,a≠b。)如果分解該問題和合併解的時間各為d(n)和c(n),則得到遞迴式:
我們則知道,歸併時間複雜度是θ(n lg n)的了(具體看算導p20-p22)
上我自己的**
#define whi(i,a,n) for(i=(a);i霍納規則(法則)#define rep(i,a,n) for(int i=(a);i
const int maxi = 1e5+10, oo = ~0u>>1;
int l[maxi], r[maxi];
void merge_sort(int* arr, int f, int l)
}
即「秦九韶方法」 用來計算多項式
我們用d(i)來表示
可推出順推:
答案是d(n)
逆推:答案是d(0)
很容易看出可以用滾動求值,即d = a(n-1) + x * d 或 d = a(i) + x * d
**
//順推統計逆序對含義:對於乙個包含n個非負整數的陣列a[1..n],如果有i < j,且a[ i ]>a[ j ],則稱(a[ i] ,a[ j] )為陣列a中的乙個逆序對。例如,陣列(3,1,4,5,2)的逆序對有(3,1),(3,2),(4,2),(5,2),共4個。for(int i = 0, d = 0; i <= n; ++i)
d = a[n-i] + x * d;
//逆推
for(int i = n, d = 0; i >= 0; ++i)
d = a[i] + x * d;
很快就能用插入排序來統計,但o(n^2)咱們不採用,咱們用o(n lg n)的歸併啦 >_<
**
#define whi(i,a,n) for(i=(a);i#define rep(i,a,n) for(int i=(a);i
const int maxi = 1e5+10, oo = (~0u>>1)+1;
typedef unsigned long long ull;
ull cnt;
int l[maxi], r[maxi];
void mi_cnt(int* arr, int f, int l)
else
arr[f++] = r[j++];
}}
逆序對 (歸併排序)
逆序對的nlogn方法,改進後的歸併排序 給定排列p,求排列的逆序對數量。p的長度 100000。要求o nlogn 定義歸併排序過程merge l,r merge l,r merge l,mid merge mid 1,r count l,mid,mid 1,r 只需要考慮左右兩段之間造成的逆序對...
歸併排序 逆序對
按照劉汝佳說的,歸併排序分三步 1.劃分問題,即把序列分成元素盡量相等的兩半 2.遞迴求解 3.合併子問題 其實就是把乙個序列不斷的二分,直到只有兩個元素的時候,然後排序,然後返回,再排序。先上 include using namespace std long long a 100005 t 100...
歸併排序(逆序對)
現在我們在競賽中最常用的排序是快速排序,c 只要乙個sort就搞定,但非常明顯,歸併排序的時間複雜度是最優的而且非常穩定,但是人們經常把它用在求逆序對個數上面。那麼下面我用乙個這樣的題來講一下歸併排序。點這裡看題目和樹狀陣列解法。歸併排序是將數列a l,h 分成兩半a l,mid 和a mid 1,...