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; }