题意:Alice有n张牌,Bob有n张牌,A能覆盖B当且仅当A的长宽不小于B的长宽,现在输入他们的牌的长宽,求最多能覆盖多少张。
分析:
思维。先分别按长的降序排序,然后遍历A,每次都从B中选出长小于等于A的长的牌,把他们的宽放进multiset,然后利用lower_bound()函数找出A的宽能覆盖的最长的宽从multiset中删除。以此类推。这样做就保证了局部操作的最优性,这也是这题的贪心策略。
B中牌每张只可能进一次multiset所以是O(n),查询用lg(n)所以总的时间复杂度是O(nlgn)
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<set>
using namespace std;
struct node{
int x,y;
};
int t,n;
node a[100005],b[100005];
multiset<int> s;
bool cmp(node a,node b)
{
return a.x<b.x;
}
int main()
{
scanf("%d",&t);
while(t--){
s.clear();
multiset<int> ::iterator it;
int ans=0;
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d%d",&a[i].x,&a[i].y);
for(int i=0;i<n;i++) scanf("%d%d",&b[i].x,&b[i].y);
sort(a,a+n,cmp);
sort(b,b+n,cmp);
int j=0;
for(int i=0;i<n;i++){
while(j<n&&a[i].x>=b[j].x){
s.insert(b[j].y);
j++;
}
if(s.size()>=1){
it=s.lower_bound(a[i].y);
if (it == s.end()) it--;
if (it != s.begin() && *it > a[i].y) it--;
if (*it <= a[i].y ) {
s.erase(it);
ans++;
}
// if(it!=s.begin()&&*it<=a[i].y){
// ans++;
// s.erase(it);
// }
}
}
printf("%d\n",ans);
}
}