【LuoguP3611 】[USACO17JAN]Cow Dance Show S 优先队列

二分 + 优先队列

链接


传送门

概述

经过几个月的排练,奶牛们基本准备好展出她们的年度舞蹈表演。今年她们要表演的是著名的奶牛芭蕾——“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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值