Genius ACM(倍增 歸併排序)

2021-10-02 10:23:03 字數 2051 閱讀 8301

傳送門

給定乙個整數 m,對於任意乙個整數集合 s,定義「校驗值」如下:

從集合 s 中取出 m 對數(即 2∗m 個數,不能重複使用集合中的數,如果 s 中的整 數不夠 m 對,則取到不能取為止),使得「每對數的差的平方」之和最大,這個最大值 就稱為集合 s 的「校驗值」。

現在給定乙個長度為 n 的數列 a 以及乙個整數 t。我們要把 a 分成若干段,使得 每一段的「校驗值」都不超過 t。求最少需要分成幾段。

1列舉每乙個分塊[l,r]的l,在l一定的情況下根據倍增思路不斷更新r值,直到不能更新為止,確定乙個分塊。

在求分塊的「校驗值」時,若對整個分塊進行sort,整體時間複雜度為o(n

log2

n)o(nlog^n)

o(nlog

2n),需要對此進行優化。

當前分塊左邊界為l,已確定的滿足條件的右邊界為r,下乙個需要檢驗的右邊界為r+p。[l,r]已有序,在對[r+1,r+p]sort後,根據歸併排序的思路將這兩個區間合併為有序區間[l,r+p],再進行檢驗。據說整體時間複雜度可降到o(n

logn

)o(nlogn)

o(nlog

n)。(倍增的過程最多迴圈o(l

ogn)

o(logn)

o(logn

)次,累計擴充套件長度為o(n

)o(n)

o(n)

,好像差不多是這樣)

a紀錄有序區段,[l,r](有序) 和[r+1,r+p](無序)

b只擷取a中的[r+1,r+p],並進行sort

c是歸併排序時的臨時陣列,記錄有序的[l,r+p]

[l,r+p]可行,更新a[l,r+p]的元素排列(即c中記錄的內容),r+=p,p*=2;

否則p/=2,a不做任何更新;

這樣的話用到了3個陣列。

還要加快讀,否則只過90%

打擾了,同樣的**偶爾會超時。。?

#include

using

namespace std;

typedef

long

long ll;

const

int maxn =

5e5+10;

ll n, m, t;

ll k;

ll a[maxn]

, b[maxn]

, c[maxn]

;inline ll read()

while

(ch>=

'0'&& ch<=

'9')

return x;

}bool

check

(ll l, ll r)

void

sort

(ll l, ll r, ll p)

}int

main()

else p>>=1;

} ans++

; r++;if

(r==n) ans++

; l = r; p =1;

}printf

("%d\n"

, ans);}

return0;

}

歸併排序(2 路歸併排序)

遞迴寫法 include define maxn 100 void merge int a,int l1,int r1,int l2,int r2 將陣列a的區間 l1,r1 和區間 l2,r2 合併為乙個有序區間 else while i r1 while j r2 for int i 0 i非遞...

python歸併排序 python 歸併排序

排序思路 1.將陣列分成兩組a,b,建立臨時陣列 c,c長度 a b 2.i,j分別屬於a,b 3.若a i b j 將b j 放入c,j 否則 a i 放入c,i 4.迴圈3步驟,將a或b中剩餘的元素放入c,再將c複製到陣列中 5.遞迴3 4直到a,b序列的長度 1 歸併排序 class merg...

排序 歸併排序

歸併 merge 排序法是將兩個 或兩個以上 有序表合併成乙個新的有序表,即把待排序序列分為若干個子串行,每個子串行是有序的。然後再把有序子串行合併為整體有序序列。歸併 將兩個已經排好序的集合合併到乙個集合眾,並且保證新的集合也是有序的。核心點 只有乙個元素的集合是已經排好序的集合。歸併排序是建立在...