對於給定的乙個長度為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 段和為 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 3
4 2 4 5 1
輸出 #1
6
分析
上下有界且單調,最大值求最小,最小值求最大,想到二分搜尋的應用
while (left <= right)
基本**如上,現在對check寫函式,求每段和的最大值,則,每次規定mid,對,遍歷資料,只要不超過mid就把它們放在乙個段內,求當前選的這個最大值的最小(mid),求每段不大於mid的最小劃分數,,看看能分多少段。r 設為最大的數,即可以設為數列的和,l 設為較小的數可以設為數列的最大值
#include #include using namespace std;
const int n = 100004;
int n, m;
int arr[n];
int check(int k)
else
}return ans > m;//如果分段大於要分的段數了,說明mid選大了,反之則選小了
}int main(void)
while (left <= right)
cout << left;
}
數列分段 Section II
對於給定的乙個長度為n的正整數數列 a i 現要將其分成 m m n 段,並要求每段連續,且每段和的最大值最小。關於最大值最小 例如一數列 4 2 4 5 1 要分成 3 段 將其如下分段 42 45 1 第一段和為 6 第 2 段和為 9 第 3 段和為 1 和最大值為 9 將其如下分段 4 24...
數列分段 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...