题目链接:戳我
开始以为是按照修建时间短的排序,先把修建时间短的修了。
但是这样显然有问题,因为可能前面的倒塌时间靠后,你先修了,后面塌的就不能修了。
所以要按倒塌时间排序开始修。
然后如果当前的建筑物来得及修,当然是要修的。
这时候我们维护一个已经修过的建筑物的大根堆(优先队列)。
如果不能修,看看是否从原先修建过的建筑物中取出那个时间最长的之后,就可以修这个了。如果可以的话,就把堆顶pop掉,然后把这个放进堆中,表示不修那个修这个。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define MAXN 300010
using namespace std;
int n,ans,now;
priority_queue<int,vector<int>,less<int> >q;
struct Node{int a,b;}node[MAXN<<1];
inline bool cmp(struct Node x,struct Node y){return x.b<y.b;}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&node[i].a,&node[i].b);
sort(&node[1],&node[n+1],cmp);
// for(int i=1;i<=n;i++)printf("%d %d\n",node[i].a,node[i].b);
for(int i=1;i<=n;i++)
{
// printf("i=%d now=%d %d %d\n",i,now,node[i].a,node[i].b);
if(now+node[i].a>node[i].b&&(!q.empty()))
{
int u=q.top();
if(now-u+node[i].a<=node[i].b&&u>node[i].a)
{
now=now-u+node[i].a;
q.pop();
q.push(node[i].a);
}
}
else ans++,now+=node[i].a,q.push(node[i].a);
}
printf("%d\n",ans);
return 0;
}