数列分段 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
5 3
4 2 4 5 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\)。
解法&个人感想
其实这题我觉得没什么要说的 嘿嘿
因为跟前面那题跳石头思路太像了
主要就是要强调一个l,r赋初值的范围
我们都知道平时l一般赋值是1或者0 r我的个人习惯是1e9
但是本题中因为有阴间的hack数据 由题意得知我们此时为了取出最大的一个序列
而每个序列至少含有一个数字 所以l应该取a[i]中最大的那个值
而平时也经常看到r取a[i]之和 这里不加赘述
#include<bits/stdc++.h> #define ll long long using namespace std; int n,m; int a[100005]; bool check(int x){int cnt=1,ans=0;for(int i=1;i<=n;i++){if(ans+a[i]>x){ans=0;cnt++;}ans+=a[i];}return cnt<=m; } int main(){scanf("%d%d",&n,&m);int l=0,r=0,mid;for(int i=1;i<=n;i++) {scanf("%d",&a[i]);r+=a[i];l=max(l,a[i]);}while(l<=r){mid=(l+r)/2;if(check(mid)) r=mid-1;else l=mid+1;}printf("%d",l);system("pause");return 0; }