可反悔的贪心。从小到大对倒塌时长排序,先修快倒塌的(从小到大枚举修理时长)。如果时间不够修当前的楼,就先判断这个楼是否有必要修(修它的用时<修之前楼用时的最大值,就有必要修)。如果没必要就不修,如果有必要就把前面修的时间最长的楼去掉,不去修它。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
priority_queue<ll> q;//大根堆
struct build{
    ll t1;
    ll t2;
}a[150010]; 
ll n;
int comp(struct build x,struct build y){//按照倒塌时长从小到大排序 
    return x.t2<y.t2;
}
int main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    cin >> n;
    for(int i=0;i<n;i++)
        cin >> a[i].t1 >> a[i].t2;
    sort(a,a+n,comp);
    ll pt=0;//已经过去的时间pass time 
    ll saved=0;//已经修好的楼 
    ll maxsaved=0;//最多能修好的楼 
    for(int i=0;i<n;i++){
        if(pt+a[i].t1<a[i].t2){//能修好 
            q.push(a[i].t1);
            pt+=a[i].t1;
            saved++;
            maxsaved=max(maxsaved,saved);
        }
        else{//时间不够,修不好 
            if(a[i].t1<q.top()){//当前的楼用时不是最多,有必要修当前的楼
                while(pt+a[i].t1>a[i].t2){//把前面时间长的扔了,修当前这个
                    ll x = q.top();
                    q.pop();
                    pt-=x;
                    saved--;
                }
                q.push(a[i].t1);
                pt+=a[i].t1;
                saved++;
                maxsaved=max(maxsaved,saved);
            }
        }
    }
    cout << maxsaved << "\n";
    return 0;
}

---------------------一个优化--------------------------
先假设当前这个楼能修,直接放进堆里。如果发现这个楼需要修(修这个楼用时<大根堆的堆顶),就从这个堆中把修理用时长的楼删去

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
priority_queue<ll> q;//大根堆
struct build{
    ll t1;
    ll t2;
}a[150010]; 
ll n;
int comp(struct build x,struct build y){//按照倒塌时长从小到大排序 
    return x.t2<y.t2;
}
int main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    cin >> n;
    for(int i=0;i<n;i++)
        cin >> a[i].t1 >> a[i].t2;
    sort(a,a+n,comp);
    ll pt=0;//已经过去的时间pass time 
    ll saved=0;//已经修好的楼 
    ll maxsaved=0;//最多能修好的楼 
    for(int i=0;i<n;i++){
        //先假设能修
        q.push(a[i].t1);
        pt+=a[i].t1;
        saved++;
        while(a[i].t1<=q.top() && pt>a[i].t2){//当前的楼要修,且时间不够,就删去其他用时长的楼
            ll x = q.top();
            q.pop();
            pt-=x;
            saved--;
        }
        maxsaved=max(maxsaved,saved);
    }
    cout << maxsaved << "\n";
    return 0;
}