这题很容易能想到是贪心,却一下子很难想清楚如何贪心


首先可以很容易想出这样的贪心:

对于一个机器,肯定是按照x大的先考虑,x相等时y大的先考虑。因为x的权值很大,这样钱是最多的

考虑任务的选择次序,很容易想到肯定是先考虑钱多的,再考虑钱少的

想到这里,我们就知道了,肯定要对任务按照x,y的次序从大到小排序,然后从大到小去枚举


然后好像就不知道怎么处理机器了,,这时候又可以注意到一个细节:y<=100,其实就是告诉你,y可以直接枚举,且可以用一个数组直接记数y,这样就可以避免在线性结构中查找某个y是否存在了


想到这里答案基本就出来了:

把机器和任务都按照x从大到小,x相等时y从大到小的顺序排序。

最开始,把所有机器的时间能满足任务1的都选出来,然后在这些里面选出时间符合要求的,且最小的

然后对于第i个任务,只需要在i-1操作后剩余机器的前提下,再加入能满足i的时间的机器即可

因为前面的机器的x必然大于后面的机器,所以,如果只看时间,前面的机器是肯定可以满足后面的机器所能完成的任务


#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<functional>
#include<algorithm>

using namespace std;
typedef long long LL;
typedef pair<int, int>PII;

const int MX = 100000 + 5;
#define X first
#define Y second

int cnt[MX];
PII mach[MX], work[MX];

int main() {
    int n, m;
    while(~scanf("%d%d", &n, &m)) {
        memset(cnt, 0, sizeof(cnt));
        for(int i = 1; i <= n; i++) {
            scanf("%d%d", &mach[i].X, &mach[i].Y);
        }
        sort(mach + 1, mach + 1 + n, greater<PII>());
        for(int i = 1; i <= m; i++) {
            scanf("%d%d", &work[i].X, &work[i].Y);
        }
        sort(work + 1, work + 1 + m, greater<PII>());

        LL ans = 0;
        int sum = 0;
        for(int i = 1, j = 1; i <= m; i++) {
            while(j <= n && mach[j].X >= work[i].X) {
                cnt[mach[j].Y]++;
                j++;
            }

            for(int y = work[i].Y; y <= 100; y++) {
                if(cnt[y]) {
                    sum++;
                    cnt[y]--;
                    ans += 500 * work[i].X + 2 * work[i].Y;
                    break;
                }
            }
        }

        printf("%d %I64d\n", sum, ans);
    }
    return 0;
}