链接:https://ac.nowcoder.com/acm/contest/6013/A
来源:牛客网
题目描述
疫情期间,牛牛宅在家里无事可做,于是就在网上买了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 <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <map>
using namespace std;
#define int long long
int cnt[1000005]; int n, m;
bool cmp(int a, int b) {
return a > b;
}
bool check(int t) {
int sum = 0;
for (int i = 0; i < n; i++) {
if (cnt[i] - i / t <= 0) break; 此处除以t,因为每天读的书要均匀,这样最优(而不是第一天读1本,第二天读10本),而且也可以计算出每天多看书剩余的知识力。
sum += (cnt[i] - i / t);
}
if (sum >= m) return true;
else return false;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
for (int i = 0; i < n; i++) cin >> cnt[i];
sort(cnt, cnt + n,cmp);
int l = 1, r = n; int ans = -1;
while (l <= r) {
int mid = (l + r) / 2;
if (check(mid)) {
ans = mid; r = mid - 1;
}
else l = mid+1;
}
cout << ans << endl;
return 0;
}