對於給定的乙個長度為n的正整數數列 a-i ,現要將其分成 m(m≤n)段,並要求每段連續,且每段和的最大值最小。
關於最大值最小:
例如一數列 4 2 4 5 1 要分成 3 段
將其如下分段:
[42][45][1]
第一段和為 6 ,第 2 段和為 9 ,第 3 段和為 1 ,和最大值為 9 。
將其如下分段:
[4][24][51]
第一段和為 44 ,第 22 段和為 66 ,第 33 段和為 66 ,和最大值為 66 。
並且無論如何分段,最大值不會小於 66 。
所以可以得到要將數列 4 2 4 5 1 要分成 3 段,每段和的最大值最小為 6 。
首先,分析題目,求最大值的最小化,直接聯想到二分,so我們直接二分答案,關鍵是要怎麼去高效的check,我們考慮乙個貪心的思路,能加的就加上,不能則新開一段,so對於二分的值x,我們從數列a從前往後掃,如果tot大於了x,我們不加而是tot重新賦值並且num++,最後只需判斷num是否不小於m就行了。這樣判斷與字首和一樣是o(n)的複雜度,但是節省了空間且容易思考。
注意:二分時的區間取值問題,很明顯,對於l的賦值應該取數列中的最大值,而r應該取數列的總和。
var
max,i,j,m,n,o,k,l:longint;
a:array[1..1000000]of longint;
procedure
try(e,x:longint);
var ans:int64;
i,o:longint;
begin
if e=x then
begin
write(e); exit; end;
ans:=0;
o:=(e+x+1)div
2; for i:=1
to n do
if a[i]>o then
inc(ans,a[i]-o);
if ans>=m then
try(o,x) else
try(e,o-1);
end;
begin
readln(n,m);
for i:=1
to n do
begin
read(a[i]); if a[i]>max then max:=a[i];
end;
try(1,max);
end.
數列分段 Section II
點我點我點我點我點我點我點我點我點我點我點我點我點我點我點我點我 二分答案 貪心 首先,分析題目,求最大值的最小化,直接聯想到二分,so我們直接二分答案,關鍵是要怎麼去高效的check,因為大家很容想到字首和,但實際上這個空間是可以省略的,為什麼呢?我們考慮乙個貪心的思路,能加的就加上,不能則新開一...
數列分段Section II
對於給定的乙個長度為n的正整數數列a i 現要將其分成m m n 段,並要求每段連續,且每段和的最大值最小。關於最大值最小 例如一數列4 2 4 5 1要分成3段 將其如下分段 4 2 4 5 1 第一段和為6,第2段和為9,第3段和為1,和最大值為9。將其如下分段 4 2 4 5 1 第一段和為4...
數列分段 Section II
對於給定的乙個長度為n的正整數數列 a a1 n,現要將其分成 mm m leq nm n 段,並要求每段連續,且每段和的最大值最小。關於最大值最小 例如一數列 4 2 4 5 14 2 4 5 1 要分成 33 段。將其如下分段 4 2 4 5 1 4 2 4 5 1 第一段和為 66,第 22 ...