洛谷 P4053 [JSOI2007]建筑抢修

隐身守侯 提交于 2019-11-30 19:30:31

传送门


思路

首先题意比较容易明白:
n个建筑需要修复,只能同时修一个建筑,每个建筑修复需要t1时间,且必须在t2时间前修完,否则此建筑报废
问最多能修好多少个建筑

如果一个建筑在规定时间内没有修好的话,那它就报废了
那么为了保证能修的最多,我们首先想到的就是贪心,那么如何贪心呢?
手动模拟一下就会发现,如果从前往后修,在截止时间时这个建筑可以修好,那我们就可以修这个建筑
所以我们考虑按截止时间排序,从前往后一个个修
如果在修某个建筑i时发现修不完了,就说明在前i个建筑我们最多只能修i-1个
这时,我们就把前i个中耗时最长的那个放弃,以保证省下的时间最多

那么如何放弃最长的?显然,用优先队列维护即可
于是就有了下面这份代码


代码

/*
By:Loceaner
*/
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

inline int read() {
    char c = getchar();
    int x = 0, f = 1;
    for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    return x * f;
}

const int N = 2e5 + 11;

struct node{
    int t, r;
} d[N];

bool cmp(node a, node b) {
    return a.r != b.r ? a.r < b.r : a.t < b.t;
} 
 
int n, cnt, now;
priority_queue <int> Q; 

int main() {
    n = read();
    for(int i = 1; i <= n; i++) d[i].t = read(), d[i].r = read();
    stable_sort(d + 1, d + 1 + n, cmp);
    for(int i = 1; i <= n; i++) {
        if(now + d[i].t <= d[i].r) {
            now += d[i].t, cnt++, Q.push(d[i].t);
            continue;
        }
        if(Q.empty() || Q.top() <= d[i].t) continue;
        now -= Q.top(),now += d[i].t;
        Q.pop(), Q.push(d[i].t);
    }
    cout << cnt << '\n';
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!