数列分段2
题目描述
对于给定的一个长度为 N 的正整数数列 a[i],现要将其分成 M 段,并要求每段连续,且每段和的最大值最小。
关于最大值最小:
例如一数列 4,2,4,5,1 要分成 3 段
将其如下分段:
[42],[45],[1]
第一段和为 6,第二段和为 9,第三段和为 1,和最大值为 9。
将其如下分段:
[4],[24],[51]
第一段和为 44,第二段和为 6,第三段和为 6,和最大值为 6。
并且无论如何分段,最大值不会小于 6。
所以可以得到要将数列 4,2,4,5,1 要分成 3 段,每段和的最大值最小为 6。
输入格式
第一行包含两个正整数 N,M。
第二行包含 N 个空格隔开的正整数 a[i],含义如题目所述。
输出格式
一个正整数,即每段和最大值最小为多少。
样例 #1
样例输入 #1
5 3
4 2 4 5 1
样例输出 #1
6
提示
对于 20% 的数据:1≤N≤10
对于 40% 的数据:1≤N≤1000
对于 100% 的数据,有 1≤M≤N≤100000,且 a[i] 之和不超过 1000000000。
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,a[N];
int chk(int sum)
{
int cnt=0,rest=0;
for(int i=1;i<=n;i++)
{
if(rest>=a[i])
{
rest-=a[i];
}
else
{
cnt++;
rest=sum-a[i];
}
}
return cnt<=m;
}
int find(int l,int r)
{
while(l<r)
{
int mid=(l+r)/2;
if(chk(mid))
{
r=mid;
}
else
{
l=mid+1;
}
}
return l;
}
int main()
{
cin>>n>>m;
int l=0,r=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
l=max(l,a[i]);
r+=a[i];
}
cout<<find(l,r);
return 0;
}
/*~~~~~~~~~~~~~~DLZS135~~~~~~~~~~~~~~~~~~~~*/