链接
概述
经过几个月的排练,奶牛们基本准备好展出她们的年度舞蹈表演。今年她们要表演的是著名的奶牛芭蕾——“cowpelia”。
表演唯一有待决定的是舞台的尺寸。一个大小为K的舞台可以支持K头牛同时在舞台上跳舞。在牛群中的N头牛(1<=N<=10,000)按照她们必须出现在舞蹈中的顺序方便地编号为1…N。第i头牛计划跳d[i]的特定持续时间。一开始,第1…K头牛出现在舞台上并开始跳舞。当这些牛中的某一头牛首先完成了她的部分,她会马上离开舞台并且第K+1头牛会出现在舞台上并开始跳舞。所以,舞台上总有K头奶牛在跳舞(直到表演的尾声,奶牛不够的时候)。当最后一头奶牛完成了她的舞蹈部分,表演结束,共花了T个单位时间。
显然,K的值越大,T就越小。由于表演不能拖太长,你得知了指定T的最大可能值的上限T-max。请根据这个约束,确定K的最小值。
思路
关键在于二分法的判断上,因为上场有顺序, 我们不能放在一起考虑了,先下场的是用时最短的,所以我们可以考虑维护一个小根堆。维护这只奶牛表下场的时间即可求出最大的时间。
代码
#include <cstdio>
#include <queue>
#include <cctype>
const int N = 1e5 + 10;
int a[N], n, T;
inline int read(){
int x = 0; char ch = getchar();
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)){x =(x<<1)+(x<<3)+(ch^48); ch = getchar();}
return x;
}
bool check(int k){
std::priority_queue<int, std::vector<int>, std::greater<int> > que;
for (int i = 1; i <= k; ++i) que.push(a[i]);
for (int i = k + 1; i <= n; ++i) {
que.push(que.top() + a[i]);
que.pop();
}
for (int i = 1; i < k; ++i) que.pop();
return que.top() <= T;
}
int main() {
n = read(), T = read();
for (int i = 1; i <= n; ++i) {
a[i] = read();
}
int l = 1, r = n;
while (l <= r){
int mid = (l + r) / 2;
if (check(mid)) r = mid - 1;
else l = mid + 1;
}
printf("%d\n", l);
return 0;
}