这题很容易能想到是贪心,却一下子很难想清楚如何贪心
首先可以很容易想出这样的贪心:
对于一个机器,肯定是按照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;
}