刷题(question)
Description
比赛之路多艰,做题方得提升。努力刷题的人在比赛中往往能取得很好的成绩,小红就是这样的人。
为了继续提升自己的编程实力,小红整理了一份刷题题单,并选中了题单中的 n 道编程题,将它们从 1 到 n 编号,计划用 m 天时间按照题目编号顺序做完所有的题目(一道题目只能在同一天完成,不可以使用多天完成同一道题目)。
在小红的计划中,她完成第 i 道题目的时间为 ai。因为题目有难有易,小红做题时可以找好朋友小明帮忙解题,通过询问小明一道题目的解法,可以省去这个题目的做题时间。当然了,小红做题是为了提升自己,而不是提升小明。因此小红决定一天最多求助小明一次。
本题 m 天中,小红做题时间最长一天的总耗时定义为 T(小明帮忙做的题目不计入小红的做题总时间)。请你帮小红求出 T 的最小值是多少?
Input
输入文件为 question.in。
第一行两个正整数 n, m,n,m 分别表示小红做的题目以及小红刷完这些题目计划所用天数。
第二行 n 个正整数,分别表示每个题目解题所用时间 ai。
Output
输出文件为 question.out。
输出仅一行, m 天中耗时最长一天的总耗时 T 的最小值。
Sample 1
Inputcopy | Outputcopy |
---|---|
4 2 1 2 3 3 | 3 |
Sample 2
Inputcopy | Outputcopy |
---|---|
3 4 999 999 999 | 0 |
从耗时最长一天的总耗时 T 的最小值中,就能看出是一道二分答案。
只是check里判断的比较多,代码如下:
#include<iostream>
using namespace std;
long long a[100010],n,m,ans;
bool check(int mid) {long long sum=0,ma=0,num=0;for(int i=1;i<=n;i++) {if(sum+a[i]>mid) {ma=max(a[i],ma);if(sum-ma+a[i]>mid) i--,num++,sum=0,ma=0;else {sum+=a[i];if(i==n) num++;}}else{sum+=a[i];ma=max(a[i],ma);if(i==n) num++;}}return bool(num<=m);
}
int main() {cin>>n>>m;for(int i=1;i<=n;i++) scanf("%lld",&a[i]);if(n<=m) { //特判cout<<0;return 0; } int l=1,r=2e9;while(l<=r) {int mid=(l+r)/2;if(check(mid)) {r=mid-1;ans=mid;}else {l=mid+1;}}cout<<ans;return 0;
}