原题链接
泰泰学长必须写他的课程作业。他的课程作业包含m 页.
为了提高效率,泰泰学长从某多多上买了n 杯咖啡. 对于第 i 杯咖啡泰泰学长可以摄取 ai 咖啡因. 泰泰学长打算喝一些咖啡来提高效率(每杯咖啡最多喝一次).他可以按照任何顺序喝咖啡. 泰泰学长喝每杯咖啡会马上喝完并且一滴不剩 (也就是说他不能把一杯咖啡分到两天喝).
当然,泰泰学长的课程作业不能一天写完(至少在现实生活中不能).
我们考虑泰泰学长工作的一些天。 考虑到泰泰学长喝k杯咖啡在这一天并且这写咖啡含有的咖啡因为ai1 , ai2 … aik . 那么第一杯咖啡给他提供了写ai1页的能量, 第二杯给他提供了写max(0 , ai2 - 1)页的能量, 第三杯给他写max(0 , ai3 - 2)页的能量, …,第k杯给他写max(0 , aik - k + 1 )页的能量.
如果泰泰学长在某一天没有喝咖啡,那么他一页都不会写
泰泰学长必须尽快的完成他的课程作业(花费最少的天数去完成). 你的任务是求出泰泰学长能够完成课程作业的最短时间
Input
第一行包含两个数字n , m (1 ≤ n ≤ 2 ⋅ 10^5 , 1 ≤ m ≤ 10^9) — 分别代表咖啡的杯数和要完成的页数.
第二行包含 n 个整数a1 … an (1 ≤ ai ≤ 10^9), ai 表示第i杯咖啡的咖啡因含量.
Output
如果泰泰学长不能完成他的课程作业, 输出-1. 其他情况输出泰泰学长完成任务所需要的最小时间
Examples
输入
5 8
2 3 1 1 2
输出
4
输入
7 10
1 3 4 2 1 4 2
输出
2
输入
5 15
5 5 5 5 5
输出
1
输入
5 16
5 5 5 5 5
输出
2
输入
5 26
5 5 5 5 5
输出
-1
Note
在第一个样例中,泰泰学长第一天可以喝第四杯咖啡(写1 页), 在第二天喝第一杯喝第二杯(写2 + (3 - 1) = 4 页), 第三天喝第五杯咖啡(写 2 页) 同时在第四天喝第三杯咖啡(写1 页) 所以答案是 4 . 显然没有其他方案能够在三天内写完或者用时更少.
在第一个样例中,泰泰学长第一天可以喝第三、四、二杯咖啡(写4 + (2 - 1) + (3 - 2) = 6 页), 在第二天喝第六杯(写4 页)所以答案是 2 . 显然泰泰学长不能够在一天写完.
在第三个样例中,泰泰学长第一天可以喝完所有的咖啡(写5 + (5 - 1) + (5 - 2) + (5 - 3) + (5 - 4) = 15 页).
在第四个样例中,泰泰学长不应该第一天可以喝完所有的咖啡,应该第二天喝其中的一杯咖啡. 所以在第一天泰泰学长写5 + (5 - 1) + (5 - 2) + (5 - 3) = 14 页 第二天写5 页.
在第五个样例中,泰泰学长就算是一天喝一杯咖啡也无法完成课程作业, 所以答案是-1.
题目描述
有n杯咖啡,m页作业,每杯咖啡都有不同的能量,每天喝咖啡的顺序不定,每天第一杯不减,第二杯-1,第三杯-2,依次类推,求最少多少天
思路:二分天数,判断mid天是否能完成作业,我们需要先对咖啡能量进行排序,mid天的第一杯都必须是咖啡能量较大的
比如例1:咖啡能量排序之后为 3 2 2 1 1 假设需要3天喝完,那么
第一天:3 1-1
第二天:2 1-1
第三天:2 0
需要注意,如果该天的咖啡能量为负,那么就max(0, power[j])取较大的!!
代码如下
#include <stdio.h>
#include <iostream>
#include <algorithm>
#define MAX_SZIE 2000050
using namespace std;
typedef long long ll;
int power[MAX_SZIE],m,n;
bool cmp(ll a, ll b)
{
if(a > b)
return 1;
return 0;
}
int check(ll x)
{
int i,j = 0,flag = 0; //flag用于判断杯数所要减去的能量
ll ans = m;
if(x <= 0) //如果天数<=0那么就需要区间向右移动
return 0;
//如果x天数可以做完作业,那么区间向左移动,判断更少的天数
while(ans > 0)
{
for(i = 1;i <= x;i++)
{
ans -= max(0,power[j++] - flag); //如果能量为负,就取0
if(j >= n)
break;
}
flag++;
if(j >= n && ans > 0) //如果n倍咖啡喝完,还是没有完成作业
return 0;
}
return 1;
}
int main()
{
int i;
while(~scanf("%d %d",&n,&m))
{
for(i = 0;i < n;i++)
scanf("%d",&power[i]);
sort(power, power+n, cmp);
int l = 0, r = n, mid, ans = -1;
while(l <= r)
{
mid = (l+r) / 2;
if(check(mid))
{
ans = mid;
r = mid - 1;
}
else
l = mid + 1;
}
if(check(ans))//这里需要判断二分得到的天数是否能完成,不能完成就输出-1
printf("%d\n",ans);
else
printf("-1\n");
}
return 0;
}