BZOJ1029 JSOI2007 建筑抢修 贪心+堆

题意:给定N个建筑,每个建筑有一个修理时间t1和报废时间t2,每个时刻只能修理一个建筑,求最多可以修理的建筑数
题解:首先将所有建筑按报废时间排序,由小到大枚举,用t1来维护堆,假如已经花费的时间+当前建筑的修理时间<当前建筑的报废时间,当前建筑入堆;否则,假如当前建筑的修理时间比堆顶元素小,并且删除堆顶元素后当前建筑能够维修完毕,那么删除堆顶元素,当前建筑入堆。正确性嘛……对于一个建筑,如果它在a时刻开始修理能修理完毕,那么对于一个b<a,它在b时刻开始修理也必定能修理完,而且相当于在减少了使用时间的情况下修理相同数量的建筑。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <functional>
using namespace std;
#define ll long long

const int MAXN=150000+2;
struct Build{
    ll t1,t2;
    friend bool operator<(Build x,Build y){ return x.t2<y.t2;}
}b[MAXN],t;
int N;
ll S;
priority_queue<ll> q;

int main(){
    cin >> N;
    for(int i=1;i<=N;i++) scanf("%lld %lld",&b[i].t1,&b[i].t2);
    sort(b+1,b+N+1);

    for(int i=1;i<=N;i++){
        if(S+b[i].t1<=b[i].t2) S+=b[i].t1,q.push(b[i].t1);
        else if(b[i].t1<q.top() && b[i].t1+S-q.top()<=b[i].t2) S=b[i].t1+S-q.top(),q.pop(),q.push(b[i].t1);
    }
    cout << q.size() << endl;

    return 0;
}
View Code

 

posted @ 2017-02-26 00:44  WDZRMPCBIT  阅读(143)  评论(0编辑  收藏  举报