1 条题解
-
0
思路
首先,要求收益最大化,且选择方式没后效性,可以很自然的想到贪心。
注意到题目中给定 ,,且贡献为 , 取到最大值也没有 的贡献大。我们可以对于每个机器,任务进行排序。按照 为第一关键字, 为第二关键字排序。
排完序之后,确保了 是单调递减的,这一点很重要,在后续我会反复强调。我们现在就可以枚举每一个任务,看看是否能完成。对于每一个任务,假设先不考虑等级限制,如果时间长的任务我们可以完成,那么时间短的任务更加不用说了,肯定可以完成。这样我们考虑用贪心的思想,用等级最低且能完成这个任务的机器才是最优的,这样可以节省更多高等级机器留着以后去用,因为 是单调递减的,所以对于 不用担心,前面的机器能完成,后面的机器更加能完成,主要就是 的限制了。
所以我们可以维护一个 multiset,存储所有能够完成该任务的机器的等级,注意,由于 的单调性,我们不用每一次重新维护 multiset,而是继承上一次的值。
基于贪心,且 multiset 自带排序功能,我们可以二分查找第一个大于等于任务等级的机器等级,然后累加答案。
代码
#include<bits/stdc++.h> using namespace std; typedef pair<int, int> PII; const int N = 1e5 + 10; PII a[N], b[N]; int main() { int n, m; scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) cin >> a[i].first >> a[i].second; for (int i = 1; i <= m; i++) cin >> b[i].first >> b[i].second; sort(a + 1, a + n + 1); sort(b + 1, b + m + 1); long long cnt = 0, ans = 0; multiset<int> s; s.clear(); for (int i = m, j = n; i >= 1; i--) { while (j > 0 && a[j].first >= b[i].first) { s.insert(a[j].second); j--; } auto it = s.lower_bound(b[i].second); if (it != s.end()) { cnt++; ans += 500 * b[i].first + 2 * b[i].second; s.erase(it); } } cout << cnt << " " << ans << endl; return 0; }
- 1
信息
- ID
- 1266
- 时间
- 1000ms
- 内存
- 64MiB
- 难度
- 6
- 标签
- 递交数
- 181
- 已通过
- 50
- 上传者