洛谷 P4053 [JSOI2007]建筑抢修

吐槽:你确定这是蓝题???

题目链接

题目大意

现在有\(N\)个坏掉的建筑和一个建筑工人,已知修理第\(i\)个建筑的时间是\(T1_i\)秒,但是如果在\(T2_i\)秒前没有修理完成,这个建筑就会\(boom…\)(刚好在\(T2_i\)秒修好不会炸掉)。然后建筑工人前往每个建筑的时间忽略不计,请你求出最多能够修理多少个建筑...

输入格式

第一行一个\(N\),接下来\(N\)行,每行两个数\(T1\),\(T2\),意义如上述。

输出格式

输出一个数,表示最多能修理的建筑。

样例

\(input:\)

4
100 200
200 1300
1000 1250
2000 3200

\(output:\)

3

样例解释

我们按\(1-3-2\)或者\(1-2-4\)的方式去修即珂。

思路

啊这。。您别告诉我您没看出来这是裸的贪心……

首先,我们按每个建筑爆炸的时间排序,先爆炸的先修。然后我们开一个变量来记录当前已经用了多少的时间去修理(同时就是一条时间轴)。那么显然,有些建筑会在我们修理完当前建筑后就爆炸了,那么当这个爆炸的建筑所需要修理的时间比我们修理过的建筑中最大的修理时间要小,那么我们就把修理过的消耗最大的修理时间的建筑给__掉,然后空出来的时间修理这个建筑。这个过程用一个优先队列维护即珂~~

我相信您一定是一头雾水,但是看代码您一定懂了!

\(ACcode\)

#include<bits/stdc++.h>
#define F(i,l,r) for(register int i=l;i<=r;i++)
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define p_b push_back
#define m_p make_pair
#define il inline
using namespace std;
const int N=150005;
int n,use,ans;//use表示当前修理总共用的时间,ans表示最多修多少个建筑
struct node {
	int t1,t2;//开个结构体存时间
}t[N];
priority_queue<int> q;//定义优先队列来存放我们当前所做过的任务
bool cmp(node x,node y) {
	return x.t2<y.t2;//按爆炸时间升序排序
}
int main() {
	scanf("%d",&n);
	F(i,1,n) scanf("%d%d",&t[i].t1,&t[i].t2);//输入
	sort(t+1,t+1+n,cmp);//排序
	F(i,1,n) {
		if(use+t[i].t1>t[i].t2) {//如果我们当前的任务修理不了了(没修理完或者没修理就会爆炸的那种
			if(t[i].t1<q.top()){//如果当前的任务耗费的时间比我们修过的所有任务中耗费时间最大的任务要小,那么我们就选择不去修那个耗时大的,取而代之选当前的
				use-=q.top();//减去最大的耗时
				q.pop();//弹出
				q.push(t[i].t1);//将当前任务推入队列
				use+=t[i].t1;//加上当前耗时
			}
		}
		else {//如果能修就修呗……
			q.push(t[i].t1);
			use+=t[i].t1;
			ans++;//这里一定要加,上面那个if不加的原因是:我们弹出了一个有推入了一个,修理个数还是不变
		}
	}
	printf("%d\n",ans);//输出
	return 0;
}

不得不说,水极了(首尾呼应(滑稽))

posted @ 2020-10-06 22:53  moonlateQZ  阅读(117)  评论(0)    收藏  举报