题目描述
小刚在玩JSOI提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的入侵者。但是T部落的基地里已经有N个建筑设施受到了严重的损伤,如果不尽快修复的话,这些建筑设施将会完全 毁坏。
现在的情况是:T部落基地里只有一个修理工人,虽然他能瞬间到达任何一个建筑,但是修复每个建筑都需要一定的时间。同时,修理工人修理完一个建筑才能修理下一个建筑,不能同时修理多个建筑。
如果某个建筑在一段时间之内没有完全修理完毕,这个建筑就报废了。你的任务是帮小刚合理的制订一个修理顺序,以抢修尽可能多的建筑。

输入描述:
第一行是一个整数N接下来N行每行两个整数T1,T2描述一个建筑:修理这个建筑需要T1秒,如果在T2秒之内还没有修理完成,这个建筑就报废了。

输出描述:
输出一个整数S,表示最多可以抢修S个建筑.
N < 150,000; T1 < T2 < maxlongint

题解
题意就是n个建筑需要修复,只能同时修一个建筑,每个建筑修复需要t1时间,且必须在t2时间前修完,否则此建筑报废 问最多能修好多少个建筑。初看题目,想到的可能是动规,但t的范围太大,无法定义状态。由于没有权值,所以我们肯定考虑选花时间小的建筑,于是我们把建筑按花的时间从小到大排序,能选就选,选了的我们让它在尽量靠后的时间修(一个经典贪心套路)。初始当前使用时间usetime=0,能修复建筑个数ans=0; 先按照截止时间从小到大排序,如果i能选(usetime+i.x&lt;=i.y)则选(usetime+=i.x,ans++),并把耗费时间加入到大根堆中,如果不能选(usetime+i.x&gt;i.y),则看堆顶元素与耗费时间的大小关系,判断能否减小当前时间。跟看电视那总题有点关系。
代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define lowbit(x) x&(-x)

typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll, ll> pll;

const int N = 2e5+5;
const ll mod = 1e9+7;
const int INF = 0x3f3f3f3f;
const double eps =1e-9;
const double PI=acos(-1.0);
const int dir[4][2]={-1,0,1,0,0,-1,0,1};
const int exdir[4][2]={1,1,1,-1,-1,1,-1,-1};

ll qpow(ll x,ll y){
    ll ans=1,t=x;
    while(y>0){
        if(y&1)ans*=t,ans%=mod;
        t*=t,t%=mod;
        y>>=1;
    }
    return ans%mod;
}

pii a[N];
bool cmp(pii x,pii y){
    return x.se<y.se;
}
void solve(){
    int n;cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i].fi>>a[i].se;
    }
    sort(a+1,a+1+n,cmp);
    priority_queue<int>q;
    int now=0,ans=0;
    for(int i=1;i<=n;i++){
        if(now+a[i].fi<=a[i].se)ans++,q.push(a[i].fi),now+=a[i].fi;
        else {
            int k=q.top();
            if(k>a[i].fi){
                q.pop();
                q.push(a[i].fi);
                now-=(k-a[i].fi);
            }
        }
    }
    cout<<ans;
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    //int t;cin>>t;
    //while(t--)solve(),cout<<'\n';
    solve();
    return 0;
}