BZOJ 1029 [JSOI2007]建筑抢修 (贪心 + 优先队列)

时间:2023-05-16 21:30:14

1029: [JSOI2007]建筑抢修

Time Limit: 4 Sec  Memory Limit: 162 MB
Submit: 5452  Solved: 2422
[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

HINT

Source

析:先对 t2 从小到大排序,然后再维护一个优先队列,t1 大的优先,然后每次在考虑 a[i] 时,如果能完成就直接放入队列,否则和队列首部的那个元素比较,如果完成时间比队列首部的时间要小,那么删除首部那个,插入这个,否则直接丢弃,最后队列中元素个数就是答案。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#include <list>
#include <assert.h>
#include <bitset>
#include <numeric>
#define debug() puts("++++")
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a, b, sizeof a)
//#define sz size()
#define pu push_up
#define pd push_down
#define cl clear()
#define all 1,n,1
#define FOR(i,x,n) for(int i = (x); i < (n); ++i)
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std; typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const LL LNF = 1e17;
const double inf = 1e20;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 150000 + 10;
const int maxm = 3e5 + 10;
const int mod = 10007;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, -1, 0, 1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c) {
return r >= 0 && r < n && c >= 0 && c < m;
} struct Node{
int t1, t2;
bool operator < (const Node &p) const{
return t1 < p.t1 || t1 == p.t1 && t2 > p.t2;
}
};
Node a[maxn];
inline bool cmp(const Node &lhs, const Node &rhs){
return lhs.t2 < rhs.t2;
} int main(){
scanf("%d", &n);
for(int i = 0; i < n; ++i) scanf("%d %d", &a[i].t1, &a[i].t2);
sort(a, a + n, cmp);
priority_queue<Node> pq;
int l = 0;
for(int i = 0; i < n; ++i){
if(l + a[i].t1 <= a[i].t2) pq.push(a[i]), l += a[i].t1;
else if(pq.top().t1 > a[i].t1){
l += a[i].t1 - pq.top().t1;
pq.pop(); pq.push(a[i]);
}
}
printf("%d\n", (int)pq.size());
return 0;
}