傳送門
給定乙個整數 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 排序法是將兩個 或兩個以上 有序表合併成乙個新的有序表,即把待排序序列分為若干個子串行,每個子串行是有序的。然後再把有序子串行合併為整體有序序列。歸併 將兩個已經排好序的集合合併到乙個集合眾,並且保證新的集合也是有序的。核心點 只有乙個元素的集合是已經排好序的集合。歸併排序是建立在...