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