描述
高考结束后,同学们大都找到了一份临时工作,渴望挣得一些零用钱。从今天起,Matrix67将连续工作N天(1<=N<=100 000)。每一天末他可以领取当天及前面若干天里没有领取的工资,但他总共只有M(1<=M<=N)次领取工资的机会。Matrix67已经知道了在接下来的这N天里每一天他可以赚多少钱。为了避免自己滥用零花钱,他希望知道如何安排领取工资的时间才能使得领到工资最多的那一次工资数额最小。注意Matrix67必须恰好领工资M次,且需要将所有的工资全部领走(即最后一天末需要领一次工资)。
输入格式
第一行输入两个用空格隔开的正整数N和M
以下N行每行一个不超过10000正整数,依次表示每一天的薪水。
输出格式
输出领取到的工资的最大值最小是多少。
测试样例1
输入
7 5
100
400
300
100
500
101
400
输出
500
备注
【样例说明】
采取下面的方案可以使每次领到的工资不会多于500。这个答案不能再少了。
100 400 300 100 500 101 400 每一天的薪水
<------1 <-------2 <---3 <---4 <---5 领取工资的时间
500 400 500 101 400 领取到的工资
二分,检验答案
//sineMora 2016.7.9 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> using namespace std; const int maxn = 200005; int n,m,sum[maxn]; void input(){ cin>>n>>m; int t; sum[0] = 0; for(int i = 1;i <= n;i++){ scanf("%d",&t); sum[i] = sum[i-1] + t; } } bool check(int t){ int left = m-1,add = 0; for(int i = 1;i <= n;i++){ if(sum[i] - sum[i-1] > t){ return false; } if(add + sum[i] - sum[i-1] > t){ left--; add = sum[i] - sum[i-1]; }else{ add += sum[i] - sum[i-1]; } if(left < 0) return false; } return true; } void div(){ int lans = 0,rans = sum[n],mans; while(lans <= rans){ mans = (lans + rans) >> 1; if(check(mans)){ rans = mans - 1; }else{ lans = mans + 1; } } if(check(mans)) cout<<mans; else cout<<mans + 1; } int main(){ input(); div(); return 0; }
#include<iostream> #include<cstdio> using namespace std; int n,m,a[100001],sum,mx,ans; bool jud(int x) { int t=0,tot=0; for(int i=1;i<=n;i++) { tot+=a[i]; if(tot>x){t++;tot=a[i];} if(t+1>m)return 0; } return 1; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); mx=max(mx,a[i]); sum+=a[i]; } int l=mx,r=sum; while(l<=r) { int mid=(l+r)>>1; if(jud(mid)){ans=mid;r=mid-1;} else l=mid+1; } printf("%d",ans); return 0; }
时间: 2024-10-18 00:30:44