HDU4268 Alice and Bob (贪心+multiset的应用)

题目大意:Alice和Bob各有N张卡,每张卡有宽和高两个属性,如果一张卡的宽和高都不小于另一张卡,就能将其覆盖,求Alice最多能覆盖Bob多少张卡。
题目的规模非常大,因此普通的O(n^2)算法是行不通的,所以考虑用容器做,这里用multiset
(#include<set>)自动升序排列。

思路   先按任一属性(我选宽度w)把Alice和Bob的卡分别按升序排列,然后从头遍历Alice的卡(a[i]),每次把宽度小于等于a[i]宽度的Bob的卡(b[i])放到multiset的容器中,然后从中取出高度最接近a[i]的卡被覆盖。如此反复就能得到最大值。

这里用到了一个multiset的函数   lower_bound(x)  返回第一个大于x的元素(不是小于)
                                      或        upper_bound(x)  返回第一个大于等于x的元素。

代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
using namespace std;
struct card{int h;int w;};
card a[
200000],b[200000];
multiset<int> s;
multiset<int>::iterator it;
bool order(card x,card y)
{
return x.w<y.w;
}
int main()
{
int t;
int i;
int n;
scanf("%d",&t);
for(;t>0;t--)
{
s.clear();
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,order);
sort(b,b+n,order);
int j=0;
int ans=0;
for(i=0;i<n;i++) 

           
while(j<n &&b [j].w<=a[i].w) 
            { 
                s.insert(b[j].h);  //这里只要放入高即可
                j++; 
            } 
            it=s.lower_bound(a[i].h); 
if(s.size() > 0 && it!=s.begin())it--;// 因为返回是第一个大于它的数,所以前一个必定小于等于它(升序排列)
           
if(s.size() > 0 && *it<=a[i].h) // 防止t没--也进入判断(如果it就指向开头begin也没法退呀)
            { 
                ans++; 
                s.erase(it);  //踢出,相当于已经被覆盖
            } 
        } 
printf("%d\n",ans);
}
return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_30684235/article/details/79704441