洛谷P1182 數列分段(二分 貪心)

2021-10-03 14:32:09 字數 1340 閱讀 8147

題目描述

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

1∼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 段和為 99,第 33 段和為 11,和最大值為 99。

將其如下分段:

[4][2\ 4][5\ 1]

[4][2 4][5 1]

第一段和為 44,第 22 段和為 66,第 33 段和為 66,和最大值為 66。

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

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

輸入格式

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

第 22 行包含 nn 個空格隔開的非負整數 a_iai​

,含義如題目所述。

輸出格式

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

輸入輸出樣例

輸入 #1 複製

5 34 2 4 5 1

輸出 #1 複製

6題目分析:

一般像這種確定什麼值是最合適的且答案取值範圍已知的題都可以二分求解,二分列舉每個答案。

這個題答案的範圍也很明確,肯定是從數列中最大值開始到數列所有元素和結束。那麼我們就開始從最中間的值開始嘗試,如果為了滿足這個答案,分出來的區間數多於給定區間數,那麼就說明這個答案太小了,必須嘗試更大的數,因為只有數大一些才能使區間數減少。反之,如果為了滿足這個答案,開出來的區間數過少,不夠給定的區間數,那麼就說明這個答案太大了,那麼我們就必須去嘗試更小的數,因為只有這樣開出來的區間數才會增多。

**

#include

using

namespace std;

const

int n=

1e5+10;

int n,m;

int a[n]

;bool

judge

(int x)

if(qu>=m)

return

true

;else

return

false;}

intmain()

int mid;

while

(left<=right)

cout

}

二分答案 洛谷P1182 數列分段

將一段數列分成不超過 m m 的段,使得每段的最小的最大值 一般看到最小 最大 什麼的基本都用二分 因為最大值要盡量小,所以資料必然具有單調性,所以我們可以通過二分最大值 即最終答案 來求解。中間加上判斷即可 include using namespace std int l,r,mid,a 100...

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