BZOJ 1029: [JSOI2007]建築搶修 堆,貪心,排序

just_sort發表於2017-01-19

Description

  小剛在玩JSOI提供的一個稱之為“建築搶修”的電腦遊戲:經過了一場激烈的戰鬥,T部落消滅了所有z部落的
入侵者。但是T部落的基地裡已經有N個建築設施受到了嚴重的損傷,如果不盡快修復的話,這些建築設施將會完全
毀壞。現在的情況是:T部落基地裡只有一個修理工人,雖然他能瞬間到達任何一個建築,但是修復每個建築都需
要一定的時間。同時,修理工人修理完一個建築才能修理下一個建築,不能同時修理多個建築。如果某個建築在一
段時間之內沒有完全修理完畢,這個建築就報廢了。你的任務是幫小剛合理的制訂一個修理順序,以搶修儘可能多
的建築。
Input

  第一行是一個整數N接下來N行每行兩個整數T1,T2描述一個建築:修理這個建築需要T1秒,如果在T2秒之內還
沒有修理完成,這個建築就報廢了。
Output

  輸出一個整數S,表示最多可以搶修S個建築.N < 150,000; T1 < T2 < maxlongint
Sample Input
4

100 200

200 1300

1000 1250

2000 3200
Sample Output
3

解題方法:
我們首先按照結束時間排序,那麼對於當前的建築。如果能修則修,如果不能且當前所需的時間小於之前修完的最小時間,則用這個和之前的那個換一下,整個過程用堆或者優先佇列維護就可以了。

程式碼如下:

#include <bits/stdc++.h>
using namespace std;
const int N = 150010;
struct node{
    int st, en;
    node(){}
    node(int st, int en) : st(st), en(en) {}
    bool operator <(const node &rhs) const{
        return en < rhs.en;
    }
}a[N];
priority_queue <int> que;

int main(){
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++){
        scanf("%d%d", &a[i].st, &a[i].en);
    }
    int now = 0, ans = 0;
    sort(a + 1, a + n + 1);
    for(int i = 1; i <= n; i++){
        if(now + a[i].st <= a[i].en){
            que.push(a[i].st);
            now += a[i].st;
            ans++;
        }
        else if(a[i].st < que.top() && (a[i].st + now - que.top()) <= a[i].en){
            now = a[i].st + now - que.top();
            que.pop();
            que.push(a[i].st);
        }
    }
    printf("%d\n", ans);
    return 0;
}

相關文章