【LuoguP3611 】[USACO17JAN]Cow Dance Show S

無神論者大祭司發表於2020-12-26

二分 + 優先佇列

連結


傳送門

概述

經過幾個月的排練,奶牛們基本準備好展出她們的年度舞蹈表演。今年她們要表演的是著名的奶牛芭蕾——“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;
}

相關文章