这道题明摆着就是一个二分答案,我们可以先写二分函数,再在二分函数中找答案。
那么这道题该怎么写呢?
主函数内部思路:定义一个 、
、一个有
个空间的数组
,按题目描述读入。
然后输出解。
int n,m;
int a[100005];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);//10^6次方个数输入,用scanf不会超时
}
cout<<find();
return 0;
}
二分思路:这是一个最大化还是最小化查找呢?我们得看题。最大月度开销的最小值,即最小化查找。接下来是模板
int find(){
int l=0,r=1e9+1;
while(l+1<r){
long long mid=l+r>>1;
if(check(mid))r=mid;
else l=mid;
}
return r;
}
函数内部思路(本体核心):首先要一个答案
(初始值为
,因为我一开始没有计算开销),一个
(初始值为
,如果我所有的月的开销加起来都不超过总开销,那我月数就为
),然后从
遍历
,如果你
都比我开销大了,那么我就不必要了。如果我
加上
是不超过开销的,那么很好,我要它。否则,我就要把月加一个
,把
置为
。
循环结束后,我只要判断我的月数超没超,就 OK 了。
bool check(long long x){
long long ans=0,cnt=1;
for(int i=1;i<=n;i++){
if(a[i]>x)return 0;
if(ans+a[i]<=x){
ans+=a[i];
}else{
ans=a[i];
cnt++;
}
}
return cnt<=m;
}
综上述,最终AC代码:
#include<iostream>
#include<stdio.h>
using namespace std;
int n,m;
int a[100005];
bool check(long long x){
long long ans=0,cnt=1;
for(int i=1;i<=n;i++){
if(a[i]>x)return 0;
if(ans+a[i]<=x){
ans+=a[i];
}else{
ans=a[i];
cnt++;
}
}
return cnt<=m;
}
int find(){
int l=0,r=1e9+1;
while(l+1<r){
long long mid=l+r>>1;
if(check(mid))r=mid;
else l=mid;
}
return r;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
cout<<find();
return 0;
}
给个好评,Thanks哦