对于给定的一个长度为N的正整数数列 ,现要将其分成 段,并要求每段连续,且每段和的最大值最小。
关于最大值最小:
例如一数列 要分成 段
将其如下分段:
第一段和为 ,第 段和为 ,第 段和为 ,和最大值为 。
将其如下分段:
第一段和为 ,第 段和为 ,第 段和为 ,和最大值为 。
并且无论如何分段,最大值不会小于 。
所以可以得到要将数列 要分成 段,每段和的最大值最小为 。
第1行包含两个正整数 。
第2行包含 个空格隔开的非负整数 ,含义如题目所述。
一个正整数,即每段和最大值最小为多少。
5 3
4 2 4 5 1
6
对于 的数据,有 ;
对于 的数据,有 ;
对于 的数据,有
这题我用二分来做
因为要涉及到区间和,所以,前缀和优化,然后二分答案
具体看代码
#include<iostream>
#include<cstdio>
int n, m, sum[100005];
using namespace std;
bool check(int mid)
{
int end = 1, start = 0, cnt = m;
while (cnt--)
{
while (sum[end] - sum[start] <= mid && end <= n)
end++;//枚举当前分段的右端点
start = end - 1;//记录下一段的左端点
if (start == n) return 1;
}
}
int main()
{
int ans = 0;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i)
{
int x;
scanf("%d", &x);
sum[i] = x + sum[i - 1];//前缀和
}
int left = sum[1], right = sum[n];
while (left <= right)
{
int mid = (left + right) >> 1;
if (check(mid)) ans = mid, right = mid - 1;//二分的答案其实就是题目的答案
else left = mid + 1;
}
printf("%d", ans);
return 0;
}