牛牛爱学习.
题目描述
疫情期间,牛牛宅在家里无事可做,于是就在网上买了n本书,每本书都有一个知识值为ai。每读一本书,牛牛的知识力就会上升ai点。当然了,因为牛牛的精力也是有限的,如果同一天连续读k本书,获得的知识力只能增加ai-k+1点。比如第一天看了知识值为5的书,那么牛牛会获得5点知识力,如果这一天在继续看另一本知识值为5的书,只能获得4点知识力,如果看了前面两本书后在继续看一本知识值为2的书,就只能获得0点知识力。牛牛想知道如果他要获得m点知识力,最少需要看几天。
注意:看书不需要按顺序,一本书只能看一次,书可以不看完,只要看就会增加知识力,当书增加的知识力为负时候可以选择不看,可以认为看完一本书是一瞬间的事情,看完后书就会消失。
输入描述:
第一行输入一个n(1≤n≤106)和m(1≤m≤109),第二行输入每本书的知识值ai(0≤ai≤109)。
输出描述:
输出最少要多少天才能获得大于等于m点的知识力,如果无法获得,请输出-1。
示例1
输入
4 10
4 4 4 4
输出
1
说明
第一天看完四本书知识力增加 4+3+2+1=10
示例2
输入
3 20
8 6 6
输出
3
分析:直接求解有点困难,所以二分答案,判断该答案可不可行,如果可行就判断更少的天数行不行,反之,增加天数;
#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
#define pi acos(-1)
using namespace std;
int n,m;
int a[1000005];
int b[1000005]={0}; //记录同一天看的书的数量
int check(int mid){
int sum = 0;
memset(b,0,sizeof(b));
for(int i = 0; i < n; i++){
sum+=max(0,a[i]-b[i%mid]); //知识力减去当天看的书的数量-1
b[i%mid]++; //第i%mid天看的数量+1
if(sum>=m) return 1;
}
return 0;
}
int main(){
cin>>n>>m;
for(int i = 0; i < n; i++)
cin>>a[i];
int l = 1, r = n;
int ans=-1;
sort(a,a+n,greater<int>()); //降序,保证先看知识力多的
while(l<=r){ //二分答案
int mid = (l+r)>>1;
if(check(mid)){
ans=mid;
r=mid-1;
}else l=mid+1;
}
cout<<ans<<endl;
return 0;
}