//刷二分法的第一道题目,搞懂它搞了3个多小时,恶补了二分法的基础上终于理解了,不容易,欲速则不达,必须具备相应的基础,否则过于生硬。
#include<iostream>
#include<cstdio>
using namespace std;
int a[1000000];
int judge(int mid,int a[],int n,int m)
{
int i;
int sum=0;
int t=1;//这里初值写成了t=0,实际下面的操作中导致了少算了一次。
for(i=1;i<=n;i++)
{
if(a[i]+sum>mid)
{
sum=a[i];
t++;
}
else sum=sum+a[i];
}
if(t>m)
return 1;
else return 0;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
int i;
int maxn=0,total=0;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]>maxn)
maxn=a[i];
total+=a[i];
}
int l=maxn;
int r=total;
int mid;
while(l<=r)
{
mid=(l+r)/2;
if(judge(mid,a,n,m))l=mid+1;
else r=mid-1;
}
cout<<l<<endl;//,这里错了,写成了mid这里需要考虑的是最后一次是l与r相等的情况下,下一次就结束了,所以是最后一次了,这时候如果返回的次数正好多余要求的次数即返回1的情况下,
//我们需要回到正好的状态就是让l+1,这个相当于是一个回溯的操作,即寻找可能性失败后的回退机制,所以这里是输出l,当然如果最后r与l相等的情况下
//如果返回的仍然是0,这个时候就是最佳状态了,返回mid和l是一样的。(以上分析错误的原因主要是二分法操作不熟练导致,欲速不达,二分法必须熟练掌握才能
//完全解决各种的子段最少的最大题。)
return
}