Alice and Bob
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2571 Accepted Submission(s): 828
Please pay attention that each card can be used only once and the cards cannot be rotated.
For each case, the first line is a number N which means the number of cards that Alice and Bob have respectively. Each of the following N (N <= 100,000) lines contains two integers h (h <= 1,000,000,000) and w (w <= 1,000,000,000) which means the height and width of Alice's card, then the following N lines means that of Bob's.
题意:
首先给出样例个数 T(1 ~ 50),每个样例给出 N (<= 100000)张牌,代表 Alice 和 Bob 各有 N 张牌,每张牌都有长(1 ~ 10 ^ 9)和宽(1 ~ 10 ^ 9),现要用 Alice 的牌去覆盖 Bob 的,必须长和宽都大于等于才能覆盖,问能够覆盖的最大数。
思路:
贪心 + multiset。与昨天的多校贪心题类似,先对牌统一按长由大到小排序,后用 Bob 的牌去匹配 Alice 的牌,选出 Alice 牌中长大于 Bob 长的牌,将宽放入 multiset 中,在从中选出在里面的牌中大于或者等于 Bob 牌的宽的第一个数,运用 upper_bound,之后从 multiset 中删去这张牌即可。用 multiset 的原因是可能宽度会有重复的。寻找的时候统计个数就好了。
lower_bound 返回的是第一个大于或者等于 num的数,若全部都小于则返回 end;
upper_bound 返回的是第一个大于 num 的数,若全部都小于则返回 end。
AC:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
const int MAX = 100005;
typedef struct {
int l, w;
} node;
node a[MAX], b[MAX];
bool cmp (node a, node b) {
if (a.l != b.l) return a.l > b.l;
return a.w > b.w;
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
int n;
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
scanf("%d%d", &a[i].l, &a[i].w);
}
for (int i = 0; i < n; ++i) {
scanf("%d%d", &b[i].l, &b[i].w);
}
sort(a, a + n, cmp);
sort(b, b + n, cmp);
int m = 0, ans = 0;
multiset<int> s;
for (int i = 0; i < n; ++i) {
while (m != n && a[m].l >= b[i].l) {
s.insert(a[m].w);
++m;
}
multiset<int>::iterator it;
it = s.lower_bound(b[i].w);
if (it != s.end() && *it >= b[i].w) {
++ans;
s.erase(it);
}
}
printf("%d\n", ans);
}
}