点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+10;
LL a[N];
LL n,m;
bool check(LL mid)
{
LL t=0,cnt=1;
for(LL i=0;i<n;i++){
if(a[i]>mid) return false;
if(a[i]+t>mid){
t=a[i];
cnt++;
if(cnt>m) return false;
}else t+=a[i];
}
return true;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin>>n>>m;
LL mx=0,sum=0;
for(LL i=0;i<n;i++){
cin>>a[i];
mx=max(mx,a[i]);
sum+=a[i];
}
LL l=mx,r=sum;
LL ans;
while(l<=r){
LL mid=l+(r-l)/2;
if(check(mid)){
ans=mid;
r=mid-1;
}else l=mid+1;
}
cout<<ans;
}
一道二分的题目,只能说二分的方法适用性真的很大啊,很多的题目都可以使用二分来谋求答案,而且似乎可以找到一个规律就是题目要求什么,我们就二分什么,这道题二分的是n段和中最大段的最小值
思路是我们先猜测最大二分数和,l是最大的单个元素,r是所有元素的和,然后去看能否在题目要求的分段数量中分段中的最大段的最小值小于等于猜测的值。这个过程使用了贪心的原理,我倒觉得更像是顺序原理,每一步做出符合要求的选择,能做到就做到,否则就失败