题意
有 n n n 个损坏的建筑,每个建筑修复需要 t i t_i ti 时间,每个建筑如果在 d i d_i di 时间仍然没有修好就会毁掉,问最多能修好多少个建筑。
解题方法
建筑在时间线上不断的毁掉,我们可以很容易的想到把 d i d_i di 从小到大排序,如果在这个时间之后我们就把这个建筑毁掉,然后我们就以 d i d_i di 为关键字排序,从小到大排序遍历,然后定义一个变量 n o w now now ,用来记录我们一共修了多长时间了,然后判断 n o w + t i now+t_i now+ti 与 d i d_i di 的关系,如果使小于等于的,那么我们就直接修,如果不是的话,我们就把之前修过的建筑并且耗时最长的去掉(如果这个时间大于这次修建需要的时间的话),只需要用一个大根堆就可以了,这样做一定会保证新的建筑一定能修完,这个样子可以为后面留出更多的时间。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
struct node
{
long long t1,t2;
friend bool operator < (node x,node y)
{
return x.t2<y.t2;
}
}a[3000000];
priority_queue<int>q;
int main()
{
long long n;
scanf("%lld",&n);
for(long long i=1;i<=n;i++)
{
long long x,y;
node t;
scanf("%lld%lld",&x,&y);
a[i].t1=x;
a[i].t2=y;
}
sort(a+1,a+n+1);
long long now=0;
long long ans=0;
for(long long i=1;i<=n;i++)
{
node x;
x=a[i];
// cout<<x.t1<<'\n';
if(now+x.t1<=x.t2)
{
ans++;
now+=x.t1;
q.push(x.t1);
}
else
{
long long fq=q.top();
if(fq>x.t1)
{
q.pop();
now-=fq;
now+=x.t1;
q.push(x.t1);
}
}
}
cout<<ans<<'\n';
return 0;
}