//贪心+二分
#include<iostream>
using namespace std;
const int N=1e5+10;
int n,m,a[N];
bool check(int mid){
int sum=0,seg=1;//sum每段和,seg段数初始化为1
for(int i=0;i<n;i++){
if(sum+a[i]<=mid)sum+=a[i];
else{
seg++;
sum=a[i];
}
}
return seg<=m;
}
int main(){
int l=0,r=0;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
l=max(l,a[i]);
r+=a[i];
}
while(l<r){
int mid=l+r>>1;
if(check(mid))r=mid;//段数小于等于m时
else l=mid+1;//段数大于m时
}
printf("%d\n",r);
return 0;
}
本题用贪心的思想去二分
如果不切,那么所有和即最大界限,如果全切开,那么单个最大的数即最小界限
必然存在当每段最大值最小和为mid时,段数刚好等于m段
如果sum小于mid则sum累加,否则,sum重新开始计数且段数加一
当段数小于等于m时,mid存在满足上述条件,故r=mid,
当段数大于m时,mid亦不满足,故l=mid+1.