[BZOJ]1029: [JSOI2007]建筑抢修

https://www.lydsy.com/JudgeOnline/problem.php?id=1029

题意:给出n个建筑的自爆时间和修复时间,求最多在自爆时间前能修复多少建筑。

一开始的naive想法:这不按自爆时间排个序,第二关键字为修复时间,升序就行?

但是这样是可以举出反例的,比如存在一个建筑,自爆时间略大于前一个,但是修复时间短,而前一个修复时间长,这两个只能选一个修,显然应该选后面那个修复时间短的,虽然不会增加答案,但是会减少时间

所以在对y升序排序的基础上,用一个大根堆维护之前出现的最大修复时间,在无法修复时,考虑把前面最大的替换掉(仅在当前建筑修复时间<最大修复时间时)。

贪心的后悔策略

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

using namespace std;

inline int rd(){
    int ret=0,f=1;char c;
    while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
    while(isdigit(c))ret=ret*10+c-'0',c=getchar();
    return ret*f;
}

const int MAXN=150005;

int n;
struct Node{
    int x,y;
}a[MAXN];
bool cmp(const Node &l,const Node &r){
    return l.y==r.y?l.x<r.x:l.y<r.y;
}

priority_queue<unsigned long long> Q;

int main(){
    n=rd();
    for(int i=1;i<=n;i++){
        a[i].x=rd();a[i].y=rd();
    }
    sort(a+1,a+1+n,cmp);
    long long cur=0;
    unsigned long long cnt=0;
    for(int i=1;i<=n;i++){
        if(cur+a[i].x>a[i].y) {
            if(a[i].x<Q.top()){
                cur+=(a[i].x-Q.top());
                Q.pop();Q.push(a[i].x);
            }
            continue;
        }
        cnt++;
        cur+=a[i].x;
        Q.push(a[i].x);
    }
    cout<<cnt<<endl;
    return 0;
}

本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9364400.html

原文地址:https://www.cnblogs.com/ghostcai/p/9364400.html