洛谷 P1182 數列分段Section II

2021-07-26 07:54:44 字數 1448 閱讀 3922

題目描述

對於給定的乙個長度為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,第2段和為6,第3段和為6,和最大值為6。

並且無論如何分段,最大值不會小於6。

所以可以得到要將數列4 2 4 5 1要分成3段,每段和的最大值最小為6。

輸入輸出格式

輸入格式:

輸入檔案divide_b.in的第1行包含兩個正整數n,m,第2行包含n個空格隔開的非負整數a[i],含義如題目所述。

輸出格式:

輸出檔案divide_b.out僅包含乙個正整數,即每段和最大值最小為多少。

輸入輸出樣例

輸入樣例#1:

5 3

4 2 4 5 1

輸出樣例#1:

6 說明

對於20%的資料,有n≤10;

對於40%的資料,有n≤1000;

對於100%的資料,有n≤100000,m≤n, a[i]之和不超過10^9。

分析:二分答案,然後判斷這個值能不能實現。

**:

var

l,r:int64;

i,j,k,m,n:longint;

a:array[1..100000] of longint;

function

search

(k:int64):int64;

var i:longint;

t,ans:int64;

begin

t:=a[1]; ans:=1;

for i:=2

to n do

if t+a[i]>k then

begin

t:=a[i];

inc(ans);

endelse

t:=t+a[i];

search:=ans;

end;

begin

read(n,m);

for i:=1

to n do

begin

read(a[i]);

if a[i]>l then l:=a[i];

r:=r+a[i];

end;

while ldo

begin

if search((l+r) div

2)<=m then

r:=(l+r) div

2else l:=(l+r) div

2+1;

end;

write(l);

end.

洛谷 P1182 數列分段

這是一道典型的二分答案問題 最大值最小,最小值最大 關鍵是對於細節的處理。二分的框架 l max,r sum while l r else l m 1 cout 二分的框架是普遍使用的,關鍵是檢驗函式的設計,此處的檢驗函式的含義為 是否存在一種合法的劃分,使得每段的最大值都不大於m。設計好了檢驗函式...

洛谷P1182數列分段

對於給定的乙個長度為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...

洛谷 P1182數列分段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...