Luogu P4053 [JSOI2007]建筑抢修
题目
贪心。
首先我们把所有建筑按\(ddl\)升序排序。
然后从前往后枚举每个建筑,如果当前能够修它就直接修。
如果不能直接修的话我们再看把之前修的中修复时间最长的那个去掉之后能不能修这个,如果可以就不修那个时间最长的了,改修当前这个。
口胡一下正确性:
进行第二个操作不会改变当前修了的总数。
而且如果把之间修复时间最长的那个去掉之后能够修现在这个,说明现在这个的修复时间一定比之前那个短,替换一下会让修完这个的时间更短。
因此我们在不降低答案的情况下让修的时间更短了,这个肯定是更优的。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int read(){int x=0,c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))x=x*10+c-48,c=getchar();return x;}
const int N=150007;
struct node{int t,ed;}a[N];
int operator<(node a,node b){return a.ed<b.ed;}
priority_queue<int>q;
int main()
{
int n=read(),i,ans=0;ll t=0;
for(i=1;i<=n;++i) a[i]=(node){read(),read()};
sort(a+1,a+n+1);
for(i=1;i<=n;++i)
if(t+a[i].t<=a[i].ed) ++ans,q.push(a[i].t),t+=a[i].t;
else if(q.top()>a[i].t&&t+a[i].t-q.top()<a[i].ed) t+=a[i].t-q.top(),q.pop(),q.push(a[i].t);
printf("%d",ans);
}