本题是一个贪心

  1. 采取什么样的贪心策略呢?

我们将截止时间按照升序排序,能修的话直接修,用一个大根堆来维护一个已经修的建筑时间的最大值,如果此时遇到不能修的话,我们就在前面找出已经修过的最大值,然后进行替换,为什么可以替换呢,因为对于前面来说少一个建筑的话时间就更充裕,对于当前建筑来说,前面减少了 一个更耗时的,那么他一定是可以修的。

//这意味着我们希望尽量确保我们能修复那些最后期限较近的建筑,因为它
//们的时间窗口更窄,修复它们的机会更少。如果我们错过了它们,就可能无法修复更多建筑。
#include <bits/stdc++.h>
using namespace std;
#define int long long

struct Building {
    int repair_time, deadline;
};
//定义一个结构体数组
//repair_time,起始时间
//deadline 截止日期
// 排序策略:按截止时间 `T2` 递增排序
bool cmp(Building a, Building b) {
    return a.deadline < b.deadline;
}

void solve() {
    int n;
    cin >> n;
    vector<Building> buildings(n);
    
    for (int i = 0; i < n; i++) {
        cin >> buildings[i].repair_time >> buildings[i].deadline;
    }

    // 按 `T2` 升序排序
    sort(buildings.begin(), buildings.end(), cmp);

    priority_queue<int> pq;  // 大根堆,存当前修复建筑的时间
    int total_time = 0, count = 0;//前面一共花的时间,多少间
    

    for (int i = 0; i < n; i++) {
        int t1 = buildings[i].repair_time;
        int t2 = buildings[i].deadline;

        if (total_time + t1 <= t2) {//可以修理直接修理
            // 当前修理时间可以满足 `T2`,直接加入修理队列
            pq.push(t1);
            total_time += t1;
            count++;
        } else if (!pq.empty() && pq.top() > t1) {//若当前不能修理,并且前面的最长时间大于此时则替换掉最消耗时间的
            // 若当前 `t1` 小于堆顶的修理时间,则替换掉耗时最长的
            //
            total_time -= pq.top();
            pq.pop();
            pq.push(t1);
            total_time += t1;
        }
    }

    cout << count << endl;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    solve();
    return 0;
}