[JSOI2007]建筑抢修(带反悔的贪心、优先队列)

链接:https://ac.nowcoder.com/acm/problem/20154
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

小刚在玩JSOI提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的入侵者。但是T部落的基地里已经有N个建筑设施受到了严重的损伤,如果不尽快修复的话,这些建筑设施将会完全 毁坏。
现在的情况是:T部落基地里只有一个修理工人,虽然他能瞬间到达任何一个建筑,但是修复每个建筑都需要一定的时间。同时,修理工人修理完一个建筑才能修理下一个建筑,不能同时修理多个建筑。
如果某个建筑在一段时间之内没有完全修理完毕,这个建筑就报废了。你的任务是帮小刚合理的制订一个修理顺序,以抢修尽可能多的建筑。

输入描述:

第一行是一个整数N接下来N行每行两个整数T1,T2描述一个建筑:修理这个建筑需要T1秒,如果在T2秒之内还没有修理完成,这个建筑就报废了。

输出描述:

输出一个整数S,表示最多可以抢修S个建筑.
N < 150,000; T1 < T2 < maxlongint
示例1

输入

4
100 200
200 1300
1000 1250
2000 3200

输出

3

首先按截止时间从小到大排序,然后用一个大根堆(优先队列)存维修所花费的时间,用一个变量now存当前时间。

当这个抢修这个新的房子发现时间不够时,如果大根堆堆顶大于当前任务需要花费的时间,我们可以不做那个堆顶的那个任务,做当前任务,这样我们可以在完成任务数没减少的情况下为下个任务节省一些时间。

 1 #include <bits/stdc++.h>
 2 typedef long long LL;
 3 #define pb push_back
 4 #define mst(a) memset(a,0,sizeof(a))
 5 const int INF = 0x3f3f3f3f;
 6 const double eps = 1e-8;
 7 const int mod = 1e9+7;
 8 const int maxn = 1e5+10;
 9 using namespace std;
10 
11 pair<int,int> pi[maxn];
12 priority_queue<int> qe;
13 
14 int main()
15 {
16     #ifdef DEBUG
17     freopen("sample.txt","r",stdin); //freopen("data.out", "w", stdout);
18     #endif
19     
20     int n;
21     scanf("%d",&n);
22     for(int i=1;i<=n;i++)
23         scanf("%d %d",&pi[i].second,&pi[i].first);
24     sort(pi+1,pi+1+n);
25     int now = 0;
26     for(int i=1;i<=n;i++)
27     {
28         if(qe.empty()||now+pi[i].second<=pi[i].first)
29         {
30             now += pi[i].second;
31             qe.push(pi[i].second);
32         }
33         else if(qe.top()>pi[i].second)
34         {
35             now = now - qe.top() + pi[i].second;
36             qe.pop();
37             qe.push(pi[i].second);
38         }
39     }
40     printf("%d
",qe.size());
41     
42     return 0;
43 }

-

原文地址:https://www.cnblogs.com/jiamian/p/13257887.html