1 条题解

  • 0
    @ 2026-9-2 21:44:00

    思路

    首先,要求收益最大化,且选择方式没后效性,可以很自然的想到贪心。

    注意到题目中给定 x<1440x<1440y100y\le100,且贡献为 (500×xi+2×yi)(500\times x_i+2\times y_i)yy 取到最大值也没有 xx 的贡献大。我们可以对于每个机器,任务进行排序。按照 xx 为第一关键字,yy 为第二关键字排序。

    排完序之后,确保了 xix_i 是单调递减的,这一点很重要,在后续我会反复强调。我们现在就可以枚举每一个任务,看看是否能完成。对于每一个任务,假设先不考虑等级限制,如果时间长的任务我们可以完成,那么时间短的任务更加不用说了,肯定可以完成。这样我们考虑用贪心的思想,用等级最低且能完成这个任务的机器才是最优的,这样可以节省更多高等级机器留着以后去用,因为 xix_i 是单调递减的,所以对于 xix_i 不用担心,前面的机器能完成,后面的机器更加能完成,主要就是 yiy_i 的限制了。

    所以我们可以维护一个 multiset,存储所有能够完成该任务的机器的等级,注意,由于 xix_i 的单调性,我们不用每一次重新维护 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
    上传者