题目描述
给定一个长度为N的正整数数列 A 1 ∼ N A_{1\sim N} A1∼N,现要将其分成M( M ≤ N M\leq N M≤N)段,并要求每段连续,且每段和的最大值最小。最大值最小的定义如下:例如一个数列 4 2 4 5 1 4\ 2\ 4\ 5\ 1 4 2 4 5 1 要分成3段。将其如下分段: [ 4 2 ] [ 4 5 ] [ 1 ] [4\ 2][4\ 5][1] [4 2][4 5][1]第一段和为6,第二段和为9,第三段和为1,和的最大值为9。将其如下分段: [ 4 ] [ 2 4 ] [ 5 1 ] [4][2\ 4][5\ 1] [4][2 4][5 1]第一段和为4,第二段和为6,第三段和为6,和的最大值为6。无论如何分段,最大值不会小于6。因此,将数列 4 2 4 5 1 4\ 2\ 4\ 5\ 1 4 2 4 5 1 分成3段,每段和的最大值最小为6。## 输入格式第一行包含两个正整数N和M。第二行包含N个空格隔开的非负整数 A i A_i Ai,表示数列。## 输出格式一个正整数,即每段和的最大值最小为多少。
样例 #1
样例输入 #1
5 34 2 4 5 1
样例输出 #1
6
提示
对于20%的数据,N不超过10。对于40%的数据,N不超过1000。对于100%的数据,N不超过 1 0 5 10^5 105,M不超过N, A i A_i Ai小于 1 0 8 10^8 108,答案不超过 1 0 9 10^9 109。
解题思路
这道题可以使用二分查找的思想来解决。首先,我们可以确定最大值的范围,即最大值不会小于数列中的最大值。然后,我们可以使用二分查找来确定每段和的最大值。假设我们猜测的每段和的最大值为mid,我们可以遍历数列,计算每段的和,如果和大于mid,则说明当前段的和已经超过了我们的猜测值,需要将当前段作为一段,然后继续计算下一段的和。如果我们最终得到的段数小于等于M,说明我们猜测的每段和的最大值mid是合理的,我们可以继续尝试更小的值。如果我们最终得到的段数大于M,说明我们猜测的每段和的最大值mid太小了,我们需要尝试更大的值。通过不断调整猜测值的范围,最终我们可以找到每段和的最大值的最小值。
代码实现
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;public class Main {static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));static StreamTokenizer sr = new StreamTokenizer(in);static int MAXN = (int) (1e5 + 10);static int[] arr = new int[MAXN];static int n, m;public static void main(String[] args) throws IOException {n = nextInt();m = nextInt();long max = 0, min = 0;for (int i = 1; i <= n; i++) {arr[i] = nextInt();max += arr[i];min = Math.max(arr[i], min);}long mid = 0, l = min, r = max;while (l < r) {mid = l + (r - l) / 2;if (check(mid)) { // 大于等于mr = mid;} else {l = mid + 1;}}out.println(l);out.flush();}private static boolean check(long mid) {long sum = 0, cnt = 1;for (int i = 1; i <= n; i++) {if (sum + arr[i] > mid) {sum = 0;cnt++;}sum += arr[i];}return cnt <= m;}static int nextInt() throws IOException {sr.nextToken();return (int) sr.nval;}}
以上是对题目的解题思路和代码实现的介绍。希望对你有帮助!如果有任何问题,请随时提问。