建筑抢修——贪心反悔堆

题面

小刚在玩(JSOI)提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,(T)部落消灭了所有

(z)部落的入侵者。但是T部落的基地里已经有(N)个建筑设施受到了严重的损伤,如果不尽快修复的话,这

些建筑设施将会完全毁坏。现在的情况是:(T)部落基地里只有一个修理工人,虽然他能瞬间到达任何一

个建筑,但是修复每个建筑都需要一定的时间。同时,修理工人修理完一个建筑才能修理下一个建筑,

不能同时修理多个建筑。如果某个建筑在一段时间之内没有完全修理完毕,这个建筑就报废了。你的任

务是帮小刚合理的制订一个修理顺序,以抢修尽可能多的建筑。

输入格式

第一行是一个整数(N),接下来(N)行每行两个整数(T1,T2)描述一个建筑:修理这个建筑需要(T1)秒,如果在

(T2)秒之内还没有修理完成,这个建筑就报废了。

输出格式

输出一个整数(S),表示最多可以抢修(S)个建筑.

输入输出样例

输入

4
100 200
200 1300
1000 1250
2000 3200

输出 #1复制

3

说明/提示

(N < 150,000; T1 < T2 < maxlongint)

思路

先把所有的建筑的 (T2) 按照从小到大的顺序排个序,然后再将建筑逐次的“修复”。 “修复”的过程中,我们

会遇到这样的状况:修复当前的建筑需要花费的时间加上已经使用了的时间,超过了修复当前建筑的截

止时间。如果排在这个建筑前面的已经被修复了的建筑中,有某个建筑的修复时间大于当前这个建筑

的修复时间,那么就不修复那个建筑,反而把当前的建筑修复了(取代)。 这会将当前已经使用的时间

减少,为后来修复更多的建筑提供了更大的可能。 (可以用Exchange Argument----easily证明)

代码

#include<bits/stdc++.h>
using namespace std;
priority_queue<int,vector<int> ,less<int> > heap;
long long n;
const int N=2001000;
struct node{
	long long t1,t2;
}pot[N];
long long ans;
long long sum;
bool cmp(node a,node b)
{
	return a.t2<b.t2;
}


int main()
{
	scanf("%lld",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld%lld",&pot[i].t1,&pot[i].t2);
	}
	sort(pot+1,pot+1+n,cmp);
	for(int i=1;i<=n;i++)
	{
		sum+=pot[i].t1;
		heap.push(pot[i].t1);
		if(sum<=pot[i].t2)
		{
			ans++;
		}
		else{
			sum-=heap.top();
			heap.pop();
		}
	}
	cout<<ans<<endl;
	return 0;
}

推荐博客

原文地址:https://www.cnblogs.com/bangdexuanyuan/p/13951957.html