题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4268
题 意:一个物品有两个参数x,y,当且仅当a物品的x不小于b物品的x且a物品的y不小于b物品的y时a物品能覆盖b物品,现在有个a物品的集合和b物品的集合,问a集合最多能覆盖多少个b集合中的物品
思 路:正解则用到了multiset——多重集合容器,天生有序并且允许元素重复。开始将Alice和Bob的矩形全部排好序,排序方式是先高后宽。然后Alice的矩形从小到大挑,每次选一个后将Bob的矩形中高小于等于该矩形的矩形的宽全部放进集合(注意:不是从头开始放,而是从上一次放过的位置继续,具体可见代码),然后再用upper_bound查找(upper_bound找到的是大于传入参数的第一个元素的位置),根据返回的位置判断是否有能够盖住的矩形,如果有,则将该宽的数据删除。因为下一次将Bob矩形放入集合的时候是从上一次放入矩形的最后一个位置向后继续放,所以每个矩形只会存入一次,不会造成重复和时间的浪费。
代码如下:
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <set>
using namespace std;
typedef int LL;
struct node
{
LL x, y;
} v1[100005], v2[100005];
bool cmp( node a, node b )
{
return a.x < b.x;
}
int main()
{
int T;
scanf ( "%d", &T );
while( T-- )
{
int n;
scanf ( "%d", &n );
for( int i = 0; i < n; i ++ )
scanf ( "%d %d", &v1[i].x, &v1[i].y );
sort( v1, v1+n, cmp );
for( int i = 0; i < n; i ++ )
scanf ( "%d %d", &v2[i].x, &v2[i].y );
sort( v2, v2+n, cmp );
LL ans = 0;
int i, j;
multiset<int>mst;
multiset<int>::iterator it;
mst.clear();
for( i = j = 0; i < n; i ++ )
{
for( ; j < n && v1[i].x >= v2[j].x; j ++ )//将比一里第i个矩形的h小的v2的矩形的w送人集合
mst.insert(v2[j].y);
if( mst.empty() ) continue;
it = mst.upper_bound( v1[i].y );//在集合 中查找一个刚好比v1的w的zhi大的矩形
if( it != mst.begin() ) {
ans++;
mst.erase( --it );//这个矩形的前一个刚好满足条件
}
}
printf( "%d\n", ans );
}
return 0;
}