普及練習場 分治演算法 逆序對

2021-08-14 11:52:43 字數 1671 閱讀 3361

題目鏈結

看到這個資料量,你就不應該想著去寫個暴力。

我原來已經寫過一遍這個題目了,並且還記得是歸併排序來做,但是有點記不得是怎麼推導出思路的了,因此決定重新推導一遍。我找到了原來的ppt,並且加一點自己的理解吧。

一開始的時候應該是1)+2),但是1)被分解成更小的1)和更小的2)。當只有兩個數的時候,就只有2)沒有1)了

下面的是一開始自己的想法,但是有點亂了。

假設有乙個陣列a1

,a2,

⋯,am

,am+

1,am

+2,⋯

,an ,此時按照中間分成a1

,a2,

⋯,am

和am+

1,am

+2,⋯

,an 。那麼我們計算總逆序對對數,就只需要計算從1到m的逆序對數,從m+1到n的逆序對數,以及左邊與右邊的逆序對數。對於求從1到m的逆序對數,以及m+1到n的逆序對數,顯然從形式上就知道應該是遞迴。對於左邊和右邊的逆序對數,考慮到交換左邊任意兩個數的位置,不會影響到左邊到右邊的逆序對對數,因此左邊的數可以任意交換位置。同理,右邊的也可以任意交換。

不過我想了想,好像上面這種思路對於遞迴的時候來說,有點難以接受,我決定換一種思路來考慮。實際上,如果你用暴力o(

n2) 求出所有的逆序對的時候,你會發現這些逆序對就是氣泡排序中出現的交換次數。我在想證明的時候找到了這麼一篇文章。我們有逆序對數等於氣泡排序交換次數。後來我想想這段我好像沒有發現什麼有用的結論。。。

#include 

using

namespace

std;

const

int maxn = 1000005;

long

long a[maxn];

long

long t[maxn];

void merge_sort_and_count(long

long a, int s, int e, long

long t);

void merge(long

long a, int s, int m, int e, long

long t);

long

long count = 0;

int main()

merge_sort_and_count(a, 0, n - 1, t);

cout

<< count << endl;

}return

0;}

void merge_sort_and_count(long

long a, int s, int e, long

long t)

int m = s + (e - s) / 2;

merge_sort_and_count(a, s, m, t);

merge_sort_and_count(a, m + 1, e, t);

merge(a, s, m, e, t);

}void merge(long

long a, int s, int m, int e, long

long t) else

}while(pa <= m)

while(pb <= e)

for(int i = 0; i < pt; i++)

}

普及練習場 分治演算法 P1010 冪次方

題目描述 任何乙個正整數都可以用 2 的冪次方表示。例如 137 27 23 2 0 同時約定方次用括號來表示,即 a b 可表示為 a b 由此可知,137 可表示為 2 7 2 3 2 0 進一步 7 22 2 20 2 1用2表示 並且 3 2 2 0 所以最後 137 可表示為 2 2 2 ...

普及練習場之排序

題目提供者ccf noi 評測方式雲端評測標籤noip普及組2006 難度入門難度 時空限制1000ms 128mb 提交 題解 明明想在學校中請一些同學一起做一項問卷調查,為了實驗的客觀性,他先用計算機生成了nn個11到10001000之間的隨機整數 n 100 n 100 對於其中重複的數字,只...

普及練習場之排序

p1177 模板 快速排序 總 看題目,模板啊!var n,i longint a array 1.100001 of longint procedure qsort l,r longint var i,j,temp,key longint begin if l r then exit i l j ...