题目链接:A-牛牛爱学习
题意:
疫情期间,牛牛宅在家里无事可做,于是就在网上买了n本书,每本书都有一个知识值为ai。每读一本书,牛牛的知识力就会上升ai点。当然了,因为牛牛的精力也是有限的,如果同一天连续读k本书,获得的知识力只能增加ai-k+1点。比如第一天看了知识值为5的书,那么牛牛会获得5点知识力,如果这一天在继续看另一本知识值为5的书,只能获得4点知识力,如果看了前面两本书后在继续看一本知识值为2的书,就只能获得0点知识力。牛牛想知道如果他要获得m点知识力,最少需要看几天。
注意:看书不需要按顺序,一本书只能看一次,书可以不看完,只要看就会增加知识力,当书增加的知识力为负时候可以选择不看,可以认为看完一本书是一瞬间的事情,看完后书就会消失。
解题思路:
二分法查询最优解
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e6+5;
int a[maxn];
int n, m;
bool judge(int k){
ll ans = 0;
for(int i = 0; i < n; i++){
if(a[i] - i / k > 0){ // 此处除以k,因为每天读的书要均匀,这样最优(而不是第一天读1本,第二天读10本)
ans += a[i] - i / k;
}
else{
break;
}
}
if(ans >= m){ // 此时天数足够获得m知识点
return true;
}
else{ // 不满足
return false;
}
}
int main(){
ll ans = 0;
cin >> n >> m;
for(int i = 0; i < n; i++){
cin >> a[i];
ans += a[i];
}
if(ans < m){
cout << -1 << endl; // 如果所有书的知识点都不足m
}
else{
sort(a, a+n);
reverse(a, a+n);
int l = 0, r = n;
while(l+1 < r){
int mid = (l + r) / 2; // 二分天数
if(judge(mid)){
r = mid;
}
else{
l = mid;
}
}
cout << r << endl;
}
return 0;
}