对于给定的一个长度为N的正整数数列 A1∼NA_{1\sim N}A1∼N,现要将其分成 MMM(M≤NM\leq NM≤N)段,并要求每段连续,且每段和的最大值最小。
关于最大值最小:
例如一数列 424514\ 2\ 4\ 5\ 14 2 4 5 1 要分成 333 段。
将其如下分段:
[42][45][1][4\ 2][4\ 5][1][4 2][4 5][1]
第一段和为 666,第 222 段和为 999,第 333 段和为 111,和最大值为 999。
将其如下分段:
[4][24][51][4][2\ 4][5\ 1][4][2 4][5 1]
第一段和为 444,第 222 段和为 666,第 333 段和为 666,和最大值为 666。
并且无论如何分段,最大值不会小于 666。
所以可以得到要将数列 424514\ 2\ 4\ 5\ 14 2 4 5 1 要分成 333 段,每段和的最大值最小为 666。
第 111 行包含两个正整数 N,MN,MN,M。
第 222 行包含 NNN 个空格隔开的非负整数 AiA_iAi,含义如题目所述。
一个正整数,即每段和最大值最小为多少。
5 3
4 2 4 5 1
6
对于 20%20\%20% 的数据,N≤10N\leq 10N≤10。
对于 40%40\%40% 的数据,N≤1000N\leq 1000N≤1000。
对于 100%100\%100% 的数据,1≤N≤1051\leq N\leq 10^51≤N≤105,M≤NM\leq NM≤N,Ai<108A_i < 10^8Ai<108, 答案不超过 10910^9109。
#includeusing namespace std;int n, m, ans;
int a[100010];//判断是否满足当 每段最大值为x时能分m组
bool check(int x) {int cnt = 1;int sum = 0;//每组的和for (int i = 1; i <= n; ++i) {if (sum + a[i] > x) {//a[i]需新开一组cnt++;sum = a[i];} else {//和上一组同组即可sum += a[i];}}return cnt <= m;
}int main() {cin >> n >> m;int sum = 0, maxx = 0;for (int i = 1; i <= n; ++i) {cin >> a[i];sum += a[i];maxx = max(maxx, a[i]);}int left = maxx, right = sum, mid;while (left <= right) {mid = left + (right - left) / 2;if (check(mid)) {//每段最大值可以更小ans = mid;right = mid - 1;} else {left = mid + 1;}}cout << ans;return 0;
}
上一篇:Redis 发布订阅