题意:把一个包含n个正整数的序列划分成m个连续的子序列。设第i个序列的各数之和为S(i),求所有S(i)的最大值最小是多少?
思路:设s[i]中最大值的最小值是x,则很容易想出,x能取得最大值为全序列之和sum,x能取的最小值为a[i]中的最大值max,即x的取值范围为[max,sum]。然后要做的事情就是在[max,sum]中找到x,根据习惯尿性,红果果的二分查找。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<stack>
#include<algorithm>
#define mx 1000005
#define LL long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
int a[mx];
int n,m;
bool hehe(int x){ //判断x是否为s(j)中的最大值
int k=0,sum=0;
for(int i=0;i<n;i++){
if(sum+a[i]>x)k++; //此时s(j)已经大于了x,要想x符合条件,则计算下一个s(j)
if(k>m-1){
sum=0;
return false; //此时已经分成了m堆,却还有剩余的a[i],x不符合条件
}
sum+=a[i];
}
return true;
}
int bs(int l,int r){
int mid;
while(l<r){
mid=(l+r)/2;
if(hehe(mid))r=mid; //如果是,则往左寻找符合条件的更小的x
else l=mid+1; //如果不是,则寻找往右寻找符合条件的x
}
return l;
}
int main(){
while(cin>>n>>m){
int max=-1;
LL sum=0;
for(int i=0;i<n;i++){
cin>>a[i];
if(a[i]>max)max=a[i];
sum+=a[i]*1LL;
}
cout<<bs(max,sum)<<endl;
}
return 0;
}