【BZOJ1029】 [JSOI2007]建筑抢修
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
100 200
200 1300
1000 1250
2000 3200
Sample Output
3
Solution
堆+贪心。首先,早结束的能取就要先取,所以按T2排序,能取就取。如果不能取的话,我们可以考虑把那些已经取的“替换”出来。而需要的时间最长的自然就是我们“替换”的对象。所以,如果当前的T1若小于已取集合里面最大的T1,则将集合内T1的最大值“替换”掉。用堆来维护这个过程。
Code
1 #include <cstdio> 2 #include <queue> 3 #include <algorithm> 4 using namespace std; 5 #define maxn 150010 6 struct poi{ 7 int t1, t2; 8 inline bool operator < (const poi &that) const {return t2 < that.t2 || (t2 == that.t2 && t1 < that.t1);} 9 }p[maxn]; 10 priority_queue<int> q; 11 int main() 12 { 13 int n; scanf("%d", &n); 14 for (int i = 1; i <= n; ++i) 15 scanf("%d%d", &p[i].t1, &p[i].t2 ); 16 std::sort(p + 1, p + n + 1); 17 long long sum = 0; 18 int cnt = 0; 19 for (int i = 1; i <= n; ++i) 20 { 21 if (p[i].t1 + sum <= p[i].t2) ++cnt, q.push(p[i].t1), sum += p[i].t1; 22 else 23 { 24 if (q.size() < 1) continue; 25 int x = q.top(); 26 if (x > p[i].t1) 27 { 28 sum += p[i].t1 - x; 29 q.pop(); q.push(p[i].t1); 30 } 31 } 32 } 33 printf("%d", cnt); 34 return 0; 35 }