[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