建筑抢修(贪心讲题2)

Description

小刚在玩JSOI提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的入侵者。但是T部落的基地里已经有N个建筑设施受到了严重的损伤,如果不尽快修复的话,这些建筑设施将会完全毁坏。现在的情况是:T部落基地里只有一个修理工人,虽然他能瞬间到达任何一个建筑,但是修复每个建筑都需要一定的时间。同时,修理工人修理完一个建筑才能修理下一个建筑,不能同时修理多个建筑。如果某个建筑在一段时间之内没有完全修理完毕,这个建筑就报废了。你的任务是帮小刚合理的制订一个修理顺序,以抢修尽可能多的建筑。

Input

第一行是一个整数N,接下来N行每行两个整数T1,T2描述一个建筑:修理这个建筑需要T1秒,如果在T2秒之内还没有修理完成,这个建筑就报废了。

Output

输出一个整数S,表示最多可以抢修S个建筑。 数据范围: N<150000,T1

Sample Input

4
100 200
200 1300
1000 1250
2000 3200

Sample Output

3
 
analyze:

先把所有的建筑的 T2 按照从小到大的顺序排个序,然后再将建筑逐次的“修复”。 “修复”的过程中,我们会遇到这样的状况:修复当前的建筑需要花费的时间加上已经使用了的时间,超过了修复当前建筑的截止时间。 so,如果排在这个建筑前面的已经被修复了的建筑中,有某个建筑的修复时间大于当前这个建筑的修复时间,那么就不修复那个建筑,反而把当前的建筑修复了(取代)。 这会将当前已经使用的时间减少,为后来修复更多的建筑提供了更大的可能。 (可以用Exchange Argument----easily证明)

#include <iostream>
#include <cstring>
#include <queue>
#include <cstdio>
#include <algorithm>

using namespace std;

const int N=150006;

struct data {
    int t1, t2;
    bool operator < (const data &T) const {
        return t2<T.t2;
    }
} A[N];
priority_queue <int> Q;
int n, ans, cur;

int main() {
    while(scanf("%d", &n)!=EOF) {
        for(int i=0; i<n; i++) scanf("%d%d", &A[i].t1, &A[i].t2);
        sort(A, A+n);
        while(!Q.empty()) Q.pop();
        cur=ans=0;
        for(int i=0; i<n; i++) {
            if(A[i].t1+cur<=A[i].t2) ans++, Q.push(A[i].t1), cur+=A[i].t1;
            else {
                if(Q.empty()) continue;
                int val=Q.top();
                if(val<=A[i].t1) continue;
                cur-=val-A[i].t1;
                Q.pop();
                Q.push(A[i].t1);
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

 

posted @ 2016-03-12 11:11  A_Cherry  Views(410)  Comments(0)    收藏  举报