洛谷——P4053 [JSOI2007]建筑抢修

P4053 [JSOI2007]建筑抢修

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

对于每一个数相当于有了两个标准,单纯排序过这道题是不可能的

首先按照$t_2$排序,再次按照$t_1$贪心模拟,

若当前的$T$所用总时间$>t_2$,考虑将前面$t_1$时间最大的哪个去除,转而添加当前$t_1$(若当前$t_1$比前面的小的话)

可以发现,若总时间超过,你去掉那个最大值,会使总时间减小,对后面的影响减小

用堆维护这个最大值即可

#include<bits/stdc++.h>

#define N 1500000
using namespace std;

int n,ans;
struct node{
    int t1,t2;
}e[N];

bool cmp(node A,node B){
    return A.t2==B.t2 ? A.t1<B.t1 : A.t2<B.t2;
}

priority_queue<int>Q;

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&e[i].t1,&e[i].t2);
    
    sort(e+1,e+1+n,cmp);
    
    int T=0;
    for(int i=1;i<=n;i++){
        if(T+e[i].t1<=e[i].t2){
            T+=e[i].t1;
            ++ans;
            Q.push(e[i].t1);
        }else{
            if(!Q.empty()&&e[i].t1<Q.top()){
                T=T-Q.top()+e[i].t1;
                Q.pop();
                Q.push(e[i].t1);
            }
        }
    }
    
    printf("%d
",ans);
    
    return 0;
}
原文地址:https://www.cnblogs.com/song-/p/9814317.html