bzoj1029 [JSOI2007]建筑抢修

Description

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

Input

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

Output

输出一个整数S,表示最多可以抢修S个建筑. N<150000 ; T1<T2<maxlongint

Sample Input

4
100 200
200 1300
1000 1250
2000 3200

Sample Output

3

Solution

此题显然是贪心。先按 t2 排序,然后依次处理,我们维护一个大根堆, 每修理一栋建筑,我们就把这栋建筑的 t1 值加入堆,若当前无法修理 我们判断堆顶是否比这栋建筑的 t1 大,如果大,取消修理堆顶,改为修理当前建筑。这个贪心的正确性是容易证明的。处理到一个建筑时,前面的处理顺序对当前决策并无影响,所以选择放弃之前修理过的 t1 最大的必然比次大的优,因为这样虽然不能更新答案,但是可以为后面的建筑提供更多的“空间”。这样想通了代码两分钟就写好了。

#include<bits/stdc++.h>
using namespace std;

inline int read() {
    int x = 0, flag = 1; char ch = getchar();
    while (ch > '9' || ch < '0') { if (ch == '-') flag = -1; ch = getchar(); }
    while (ch <= '9' && ch >= '0') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * flag;
}

#define N 150001
#define rep(ii, aa, bb) for (int ii = aa; ii <= bb; ii++)
#define ll long long

int n;
struct node { ll t1, t2; }a[N];
bool cmp(const node x, const node b) { return x.t2 < b.t2; }
priority_queue<ll> q;

int main() {
    n = read();
    rep(i, 1, n) a[i].t1 = read(), a[i].t2 = read();
    sort(a + 1, a + 1 + n, cmp);
    ll used = 0;
    int ans = 0;
    rep(i, 1, n)
        if (used + a[i].t1 <= a[i].t2) ans++, used += a[i].t1, q.push(a[i].t1);
        else if (q.size() && q.top() > a[i].t1) used += a[i].t1 - q.top(), q.pop(), q.push(a[i].t1);
    cout << ans;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值