本题是一个贪心
- 采取什么样的贪心策略呢?
我们将截止时间按照升序排序,能修的话直接修,用一个大根堆来维护一个已经修的建筑时间的最大值,如果此时遇到不能修的话,我们就在前面找出已经修过的最大值,然后进行替换,为什么可以替换呢,因为对于前面来说少一个建筑的话时间就更充裕,对于当前建筑来说,前面减少了 一个更耗时的,那么他一定是可以修的。
//这意味着我们希望尽量确保我们能修复那些最后期限较近的建筑,因为它
//们的时间窗口更窄,修复它们的机会更少。如果我们错过了它们,就可能无法修复更多建筑。
#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;
}