P1182 数列分段 Section II
P1182 数列分段 Section II
题目描述
对于给定的一个长度为 $N$ 的正整数数列 $A_{1\sim N}$,现要将其分成 $M$($M\leq N$)段,并要求每段连续,且每段和的最大值最小。
关于最大值最小:
例如一数列 $4\ 2\ 4\ 5\ 1$ 要分成 $3$ 段。
将其如下分段:
第一段和为 $6$,第 $2$ 段和为 $9$,第 $3$ 段和为 $1$,和最大值为 $9$。
将其如下分段:
第一段和为 $4$,第 $2$ 段和为 $6$,第 $3$ 段和为 $6$,和最大值为 $6$。
并且无论如何分段,最大值不会小于 $6$。
所以可以得到要将数列 $4\ 2\ 4\ 5\ 1$ 要分成 $3$ 段,每段和的最大值最小为 $6$。
输入格式
第 $1$ 行包含两个正整数 $N,M$。
第 $2$ 行包含 $N$ 个空格隔开的非负整数 $A_i$,含义如题目所述。
输出格式
一个正整数,即每段和最大值最小为多少。
输入输出样例 #1
输入 #1
1 | 5 3 |
输出 #1
1 | 6 |
说明/提示
对于 $20\%$ 的数据,$N\leq 10$。
对于 $40\%$ 的数据,$N\leq 1000$。
对于 $100\%$ 的数据,$1\leq N\leq 10^5$,$M\leq N$,$A_i < 10^8$, 答案不超过 $10^9$。
思路分析 + 代码实现
题目求的是“最大的最小”,所以采用二分答案的方法。对于每个 $mid$ ,检查是否能将数组分成不超过 $M$ 段,使得每段和不超过 $mid$。如果可以,说明 $mid$ 是一个可行解,尝试更小的 $mid$ ;如果不行,说明 $mid$ 太小,需要增大 $mid$ 。
二分查找的核心是判断是否能将数组分成 $cnt <= M$ 段,使得每段的和都不超过 $mid$ 。我们用变量 $acc$ 累计本段的和,当 $acc + a[i] > mid$ 时,分出一段,让 $a[i]$ 在新一段的开头,并更新 $cnt$ 和 $acc$ 。但是!有一个细节要注意,这个逻辑能正确工作,有一个隐含的前提: $mid$ 必须大于等于数组中的最大元素 $ma$ 。如果 $mid < ma$,那么数组中存在至少一个元素 $a[i] = ma$,它无法被任何一段容纳(因为 $a[i] > mid$),在这种情况下,判断的逻辑就失效了。所以在读入的过程中记录 $ma$ ,二分时将 $l$ 设为 $ma$ 即可解决。代码如下,时间复杂度 $O(n\operatorname{log}n)$ 。
1 |
|