思路:二分答案+贪心。
//返回我们在当前得到的二分答案下最多能开的组别
//如果分的组太多的话,说明x小了,很多的数字和都超过了他,导致分的组多了
//如果分的组太少的话,说明x大了,导致很多的数字都符合加入的条件,导致分的组很少
//如果分的组大于等于m说明当前的x可能是我们的最终解,但还是要向右边搜索来找到最大值
//如果分的组小于m,说明x太大了,分的组遥遥不够,并且大于他的全都是非法解,我们直接在mid-1的左方继续进行二分即可
代码
#include<bits/stdc++.h>
using namespace std;
int r,l,m,n,mid,a[100005];
inline bool check(int x){
int tot=0,num=0;
for(int i=1;i<=n;i++){
if(tot+a[i]<=x)tot+=a[i];//如果当前的tot加上a[i]小于等于x我们就将他加入到组里面来
//否则在当前x下,它已经超过了,我们将当前a[i]赋值给tot,并且新开一个组,num加1;
else tot=a[i],num++;
}
return num>=m;
//返回我们在当前得到的二分答案下最多能开的组别
//如果分的组太多的话,说明x开小了,很多的数字和都超过了他,导致分的组很多
//如果分的组太少的话,说明x开大了,导致很多的数字都符合加入的条件,导致分的组很少
//如果分的组大于等于m说明当前的x可能是我们的最终解,但还是要向右边搜索来找到最大值
//如果分的组小于m,说明x太大了,分的组遥遥不够,并且大于他的全都是非法解,我们直接在mid-1的左方继续进行二分即可
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i],l=max(l,a[i]),r+=a[i];
while(l<=r){
mid=(l+r)>>1;
if(check(mid))l=mid+1;
else r=mid-1;
}
cout<<l;
return 0;
}