题目链接 POJ 3614 Sunscreen
题目大意
有C头牛要涂防晒霜去晒太阳。每头牛需要涂抹的防晒霜的SPF值不同,第i头牛涂抹的防晒霜SPF必须在 [minSPFi,maxSPFi] 之间才能起作用。现在有防晒霜L瓶,每瓶的SPF值为 SPFi ,第i瓶可供 coveri 头牛使用。
现在要求最多能满足多少头牛的需求。
输入格式:
第一行 C, L
接下来2~C+1行, 每行两个数字 minSPFi , maxSPFi
接下来L行, 每行两个数字, SPFi , coveri
输出格式:
一个数字, 表示最多能满足多少头牛的需求
题解:
先给牛按照 minSPFi 升序排序, 防晒霜按照 SPFi 升序排序。
需求被满足的牛的数量受限于防晒霜的数量。我们按 SPFi 升序枚举防晒霜, 用贪心的策略将它涂在不同的牛身上。
这里的贪心策略是: 当一瓶防晒霜同时符合多头牛的需求时, 将其涂在 maxSPFi 最小的牛身上。
因为防晒霜是按升序排序的, 对于 maxSPFi 更大的牛,或许在此在之后还有 SPFi 更大的防晒霜也可以满足这头牛, 但却不一定能符合当前 maxSPFi 较小的牛了。
对于每瓶防晒霜 bottlei , 将 minSPF 小于 SPFi 的牛的 maxSPF 放入优先队列, 每次取出队列中 maxSPF 的最小值 min_maxSPF 。如果 min_maxSPF 小于当前 SPFi 则这个牛已经不可能再找到符合它需求的防晒霜了。然后把 bottlei 的 coveri 用完, 或者队列为空, 则当前这瓶防晒霜已经处理完毕, 开始枚举下一瓶。
对于处理前一瓶时队列中剩下的 maxSPF , 这些牛的 minSPF 也一定小于当前防晒霜的 SPF , 所以它们的处理方式与新加入队列的 maxSPF 是相同的。
代码:
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdio>
#define MAXL 2510
#define MAXC 2510
using namespace std;
typedef pair<int, int> Pair;
int C, L;
Pair cow[MAXC];
Pair bottle[MAXL];
priority_queue<int, vector<int>, greater<int> > q;
int main() {
cin >> C >> L;
for (int i = 0; i < C; i++)
cin >> cow[i].first >> cow[i].second;
for (int i = 0; i < L; i++)
cin >> bottle[i].first >> bottle[i].second;
sort(cow, cow+C);
sort(bottle, bottle+L);
int cur = 0;
int ans = 0;
for (int i = 0; i < L; i++) {
while (cur < C && cow[cur].first <= bottle[i].first)
q.push(cow[cur++].second);
while (!q.empty() && bottle[i].second) {
int min_MaxSPF = q.top();
q.pop();
if (min_MaxSPF >= bottle[i].first) {
ans++;
bottle[i].second--;
}
}
}
cout << ans << endl;
return 0;
}