洛谷P1182 數列分段 Section II

2021-10-04 10:52:49 字數 1740 閱讀 8932

題目描述

對於給定的乙個長度為n的正整數數列 a_a

1∼n​

,現要將其分成 mm(m\leq nm≤n)段,並要求每段連續,且每段和的最大值最小。

關於最大值最小:

例如一數列 4 2 4 5 1 要分成 3 段。

將其如下分段:

[4 2][4 5][1]

第一段和為 6,第 2 段和為 9,第 3 段和為 11,和最大值為 9。

將其如下分段:

[4][2 4][5 1]

第一段和為 4,第 2 段和為 6,第 3 段和為 6,和最大值為 6。

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

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

輸入格式

第 1 行包含兩個正整數 n,mn,m。

第 2 行包含 nn 個空格隔開的非負整數 a_ia

i ,含義如題目所述。

輸出格式

乙個正整數,即每段和最大值最小為多少。

輸入輸出樣例

輸入 #1複製

5 34 2 4 5 1

輸出 #1複製

6說明/提示

對於 20%20% 的資料,n\leq 10n≤10。

對於 40%40% 的資料,n\leq 1000n≤1000。

對於 100%100% 的資料,1\leq n\leq 10^5 1≤n≤10

5,m\leq nm≤n,a_i < 10^8

i<10 8 , 答案不超過 10^910

9

題目鏈結,點這裡

這道題要使用貪心和二分的思想來做,我一開始朦朦的,看了洛谷裡的題解也沒有講到重點。先上**吧。

#include

using

namespace std;

int n,m,left=

0,right=

0,mid;

int a[

100010];

bool

check

(int k)

//尋找當和不超過mid時能分的段數

else

}return cnt>m;

//這是重點,如果分的段數大於要分的段數 (cnt>m)

}//說明mid(k)這個數選小了,所以要找的這個數在mid的右邊

//如果分的段數小於要分的段數 (cnt<=m)

intmain()

//說明mid(k) 這個數選大了,要找的那個數在mid的左邊

while

(left<=right)

//要找的數 每段和的最大值裡的最小值 一定在這個區間內

cout<}

1 . 要求每段和最大值的最小,那麼這個數一定在這個數列的最大值和數列和之間。所以將left設為數列的最大值,right設為數列和

2.將問題拆成若干個 數列分段section i 問題,求當前選的這個最大值的最小(mid),讓每段和不大於mid,看看能分多少段。

3.如果分的段數大於要分的段數 (cnt>m) ,說明mid(k)這個數選小了,所以要找的這個數在mid的右邊。

4.如果分的段數小於要分的段數 (cnt<=m) , 說明mid(k) 這個數選大了,要找的那個數在mid的左邊 。

5. 如果相等,繼續往mid左找 , 貪心嘛再看看有沒有更小的。

6. 知道二分查詢結束,輸出結果

洛谷 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...