期望得分:80+30+70=180

实际得分:10+30+70=110

 

T1 水题(water)

Time Limit:1000ms   Memory Limit:128MB

 

题目描述

LYK出了道水题。

这个水题是这样的:有两副牌,每副牌都有n张。

对于第一副牌的每张牌长和宽分别是xi和yi。对于第二副牌的每张牌长和宽分别是aj和bj。第一副牌的第i张牌能覆盖第二副牌的第j张牌当且仅当xi>=aj并且yi>=bj。(注意牌不能翻转)当然一张牌只能去覆盖最多一张牌,而不能覆盖好多张。

LYK想让两副牌的各n张一一对应叠起来。它想知道第二副牌最多有几张能被第一副牌所覆盖。

 

输入格式(water.in)

    第一行一个数n。

    接下来n行,每行两个数xi,yi。

    接下来n行,每行两个数aj,bj。

 

输出格式(water.out)

输出一个数表示答案。

 

输入样例

3

2 3

5 7

6 8

4 1

2 5

3 4

 

输出样例

2

 

数据范围

对于50%的数据n<=10。

对于80%的数据n<=1000。

对于100%的数据1<=n<=100000,1<=xi,yi,aj,bj<=10^9。

 

对所有的牌按长从小到大排序,x相同时,第二副牌位置靠前

然后枚举所有的牌

如果是第二副牌,就把它的宽 扔到某个数据结构里

如果是第一副牌,就在这个数据结构里找<=它的宽的最大的,数据结构里把它删去,ans++

 

数据结构如果是数组,n^2,可得80

数据结构用权值线段树、平衡树、multiset 可得100

 

#include<set>
#include<cstdio>
#include<algorithm>

using namespace std;

#define N 100001

struct node
{
    int x,y,ty;
}e[N<<1];

multiset<int>s;

multiset<int>::iterator it;

bool cmp(node p,node q)
{
    if(p.x!=q.x) return p.x<q.x;
    return p.ty>q.ty; 
}

int main()
{
    freopen("water.in","r",stdin);
    freopen("water.out","w",stdout);
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&e[i].x,&e[i].y),e[i].ty=1;
    for(int i=1;i<=n;i++) scanf("%d%d",&e[i+n].x,&e[i+n].y),e[i+n].ty=2;
    sort(e+1,e+n*2+1,cmp);
    n<<=1; int ans=0;
    for(int i=1;i<=n;i++)
        if(e[i].ty==2) s.insert(e[i].y);
        else 
        {
            if(s.empty()) continue;
            it=s.upper_bound(e[i].y);
            if(it==s.begin()) continue;
            it--;
            ans++; 
            s.erase(it);
        }
    printf("%d",ans);
} 
View Code

相关文章: