题目描述
对于给定的一个长度为 𝑁N 的正整数数列 𝐴1∼𝑁A1∼N,现要将其分成 𝑀M(𝑀≤𝑁M≤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,M。
第 22 行包含 𝑁N 个空格隔开的非负整数 𝐴𝑖Ai,含义如题目所述。
输出格式
一个正整数,即每段和最大值最小为多少。
代码:
package lanqiao;
import java.util.*;
public class Main {
static int N,M; //N个数 M段
static int a[];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
M = sc.nextInt();
a = new int[N + 1];
int l = 0;
int r = (int)1e9;
long ans = 0;
for(int i = 0;i < N;i ++)
{
a[i] = sc.nextInt();
ans += a[i];
//边界最小为数组最大的元素
l = Math.max(l,a[i]);
}
//边界最大为数组之和
ans = r = (int)Math.min(r,ans);
while(l <= r)
{
int mid = (l +r) / 2;
int t = 0;
int cnt = 0;
for(int i = 0;i < N;i ++)
{
t += a[i];
if(t > mid)
{
t = a[i];
cnt += 1;
}else if(t == mid && i < N - 1)
{
t = 0;
cnt += 1;
}
}
if(cnt > M - 1)
{
l = mid + 1;
}else{
r = mid - 1;
ans = mid;
}
}
System.out.println(ans);
}
}