上海计算机学会2026年4月月赛C++乙组T3 轻重缓急(二)
·
轻重缓急(二)
题目描述
有 NNN 件事,其中第 iii 件事需要 TiT_iTi 分钟完成。一个人从 000 时刻开始工作,每分钟只能做一件事,且一件事做到一半的时候,不能停下换另一件事。
每件事都有一个过期时间。第 iii 件事的最晚启动时间为 DiD_iDi,其含义是,第 iii 件事必须在 000 时刻后的 DiD_iDi 分钟内启动,否则就过期了。
请问,如何才能让尽量多的事情按期完成,输出可以完成的最大值。
输入格式
第一行:单个整数表示 NNN
第二行到第 N+1N+1N+1 行:每行两个整数表示 DiD_iDi 与 TiT_iTi
输出格式
单个整数:表示答案
数据范围
- 30% 的数据:1≤N≤20,0≤Di≤100,1≤Ti≤1001≤N≤20,0≤D_i≤100,1≤T_i≤1001≤N≤20,0≤Di≤100,1≤Ti≤100
- 50% 的数据:1≤N≤10001≤N≤10001≤N≤1000
- 100% 的数据:1≤N≤300000,0≤Di≤1018,1≤Ti≤10181≤N≤300000,0≤D_i≤10^{18},1≤T_i≤10^{18}1≤N≤300000,0≤Di≤1018,1≤Ti≤1018
样例数据
样例1
输入:
2
5 10
6 9
输出:
1
说明:两件事只能做一件,开始任何一件都来不及做另一件事。
样例2
输入:
2
4 10
0 4
输出:
2
说明:先做第二件事,再做第一件事
题解
我来为你讲解这道题的解题思路和带注释的核心代码,只添加注释,不修改代码逻辑。
解题思路
这道题的核心是贪心算法 + 大根堆,目标是选择最多的任务完成,满足任务启动时间限制:
- 核心规则:任务 iii 必须在 DiD_iDi 时间前启动,且任务不可中断,总耗时为已选任务的时间和。
- 排序策略:将所有任务按照
完成截止时间(D_i + T_i)从小到大排序,优先处理能更早完成的任务。 - 贪心选择:用大根堆维护已选任务的耗时,累加总耗时:
- 若当前任务能满足启动时间要求,直接加入,计数+1;
- 若不满足,替换掉堆中耗时最长的任务,减少总耗时,保证能选更多任务。
带注释的完整代码
#include <bits/stdc++.h>
using namespace std;
// 任务总数,数据范围最大3e5
int n;
// 定义任务结构体,存储最晚启动时间d和耗时t,使用long long避免溢出
struct node {
long long d, t;
};
// 存储所有任务,数组大小适配最大数据范围
node a[300005];
// 大根堆:存储已选任务的耗时,用于快速取出耗时最长的任务
priority_queue<long long> pq;
// sum:已选任务的总耗时
long long sum = 0;
// ans:最终能完成的最大任务数
int ans = 0;
// 排序规则:按 任务完成截止时间(d+t) 升序排列
bool cmp(node x, node y) {
return x.d + x.t < y.d + y.t;
}
int main() {
// 加速输入输出,应对大数据量
ios::sync_with_stdio(false);
cin.tie(nullptr);
// 输入任务数量
cin >> n;
// 输入每个任务的 最晚启动时间d 和 耗时t
for (int i = 1; i <= n; i++) {
cin >> a[i].d >> a[i].t;
}
// 按照排序规则对任务排序
sort(a + 1, a + n + 1, cmp);
// 遍历每一个任务
for (int i = 1; i <= n; i++) {
// 先将当前任务的耗时加入大根堆
pq.push(a[i].t);
// 判断:当前总耗时 ≤ 任务最晚启动时间,说明可以启动该任务
if (a[i].d >= sum) {
// 累加任务耗时
sum += a[i].t;
// 完成任务数+1
ans++;
}
// 不满足启动条件:替换掉耗时最长的任务,优化总耗时
else {
// 减去堆中最长的耗时
sum -= pq.top();
// 加上当前任务的耗时
sum += a[i].t;
// 弹出堆中最长耗时的任务
pq.pop();
}
}
// 输出最大可完成任务数
cout << ans;
return 0;
}
代码核心逻辑总结
- 排序:按任务
完成截止时间(D+T)从小到大排序,保证优先处理更紧急的任务; - 堆维护:用大根堆记录已选任务的耗时,实时调整总耗时;
- 贪心替换:当新任务无法加入时,替换掉耗时最长的任务,用更小的总耗时容纳更多任务;
- 复杂度:排序 O(nlogn)O(n\log n)O(nlogn) + 堆操作 O(nlogn)O(n\log n)O(nlogn),完美适配 3×1053×10^53×105 的大数据范围。
更多推荐
所有评论(0)