BZOJ 1029: [JSOI2007]建筑抢修
Time Limit: 4 Sec Memory Limit: 162 MB
Submit: 5866 Solved: 2634
[Submit][Status][Discuss]
Description
小刚在玩JSOI提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的
入侵者。但是T部落的基地里已经有N个建筑设施受到了严重的损伤,如果不尽快修复的话,这些建筑设施将会完全
毁坏。现在的情况是:T部落基地里只有一个修理工人,虽然他能瞬间到达任何一个建筑,但是修复每个建筑都需
要一定的时间。同时,修理工人修理完一个建筑才能修理下一个建筑,不能同时修理多个建筑。如果某个建筑在一
段时间之内没有完全修理完毕,这个建筑就报废了。你的任务是帮小刚合理的制订一个修理顺序,以抢修尽可能多
的建筑。
Input
第一行是一个整数N接下来N行每行两个整数T1,T2描述一个建筑:修理这个建筑需要T1秒,如果在T2秒之内还
没有修理完成,这个建筑就报废了。
Output
输出一个整数S,表示最多可以抢修S个建筑.N < 150,000; T1 < T2 < maxlongint
Sample Input
4
100 200
200 1300
1000 1250
2000 3200
Sample Output
3
解题思路
思路题,首先按截止时间排序。但是如果直接按截止时间做显然错误,所以我们思考持续时间。我们先贪心的选取截止时间考前的,如果发现一个选不了的,就从已经选了的挑出持续时间最长的,如果大于此时枚举的,就替换,这里用优先队列维护。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#define LL long long
using namespace std;
const int MAXN = 150005;
inline LL rd(){
LL x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-48;ch=getchar();}
return x*f;
}
int n;
LL ans;
priority_queue<int> q;
struct BUILD{
LL st,ed;
}build[MAXN];
inline bool cmp(BUILD A,BUILD B){
if(A.ed==B.ed) return A.st<B.st;
return A.ed<B.ed;
}
//inline void dfs(int x,int last,int sum){
// if(x==n+1) {ans=max(ans,sum);return;}
// if(sum+(n-x)<=ans) return;
// if(last+build[x].st<=build[x].ed) dfs(x+1,last+build[x].st,sum+1);
// dfs(x+1,last,sum);
//}
int main(){
n=rd();
for(register int i=1;i<=n;i++){
int x=rd();
build[i].ed=rd();
build[i].st=x;
}
sort(build+1,build+1+n,cmp);
// dfs(1,0,0);
LL now=0;
for(register int i=1;i<=n;i++){
if(now+build[i].st<=build[i].ed){
ans++;
q.push(build[i].st);
now+=build[i].st;
}
else{
LL x=q.top();
if(x>build[i].st) {
q.pop();
now-=x;
now+=build[i].st;
q.push(build[i].st);
}
}
}
printf("%lld",ans);
return 0;
}