题意:A, B各有n张牌,A要用自己的牌覆盖B的牌,求A最多能覆盖多少张。
牌有长h和宽w两个属性,当一张牌能覆盖另一张牌,它的长宽都必须不小于另一张牌。
做法:将A,B的牌都按h由小到大排序,然后把B的所有不大于 A[ 0 ]的 h 的牌都放入multiset中(注意,扔掉h这一维,只放w即可),
再在multiset中二分查找最后一张不大于 A[ 0 ] 的 w 的牌,找到一张最优的可覆盖的牌,将此牌删去,答案加1,之后以此类推。
#include <iostream>
#include <cstdio>
#include <set>
#include <algorithm>
using namespace std;
const int maxn = 111111;
multiset<int> mset;
int n;
struct Card {
int h, w;
} A[maxn], B[maxn];
bool comp(const Card& a, const Card& b) {
return a.h <= b.h;
}
int main()
{
int T, i, j;
scanf ("%d", &T);
while (T--) {
scanf ("%d", &n);
for (i = 0; i < n; i++)
scanf ("%d %d", &A[i].h, &A[i].w);
for (i = 0; i < n; i++)
scanf ("%d %d", &B[i].h, &B[i].w);
sort(A, A+n, comp);
sort(B, B+n, comp);
int ans = 0;
mset.clear();
multiset<int>::iterator it;
for (i = j = 0; i < n; i++) {
while (j < n && B[j].h <= A[i].h) {
mset.insert(B[j].w);
j++;
}
if (!mset.empty()) {
it = mset.upper_bound(A[i].w); //返回集合中大于A[i].w的第一个数的位置,返回值为迭代器类型
if (it != mset.begin()) {
mset.erase(--it);
ans++;
}
}
}
printf ("%d\n", ans);
}
return 0
}