UVA--11020--(Multiset的使用+二分)

B - Efficient Solutions UVA - 11020

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题意:

给你n个人,每个人有两个属性x,y。如果对于一个人p(x,y),不存在另一个人(a,b),使得a<x,b<=y或者a<=x,b<y,则认为这个人是有优势的。

思路(雨神)

动态插入每个人,统计已插入的人中,有优势的人的个数。
在这里插入图片描述
插入时,维护的集合,应该是上面的形状。假如插入p时,有(a,b)是在(x,y)这个矩形的外面时,就出去了。

反思

  1. 第一次做时,没有把题意转换成上面那张图,想了挺久的qwq。
  2. 输出格式也要注意一下,之前碰到过一次。
  3. 由于要用multiset和lower_bound时要自定义(重载)
struct point
{
    int x,y;
    bool operator <(const point &b)const
    {
        if(x==b.x)return y<b.y;
        return x<b.x;
    }
};
multiset<point>p;
  1. 之后每插入集合中的元素都满足上面的图。
  2. 维护时,把不满足的点去掉即可。(用二分加快搜索速度
multiset <point>::iterator it=p.lower_bound(temp);
//二分找到>=TEMP的点。
if(it==p.begin()||(--it)->y>temp.y)
{
//如果是第一个比temp大要进去,即比第一个还小。
//或者要满足上图的条件,前一个点要y>temp的y
  p.insert(temp);
  it=p.upper_bound(temp);
 //找到第一个严格大于temp的值,把它出集合
  while(it!=p.end()&&it->y>=temp.y)p.erase(it++);
//找不到就会it==p.end,或者剩下的点是满足条件的。
}

AC

#include <iostream>
#include <set>
#include <cstdio>
#include <vector>
#include <algorithm>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
struct point
{
    int x,y;
    bool operator <(const point &b)const
    {
        if(x==b.x)return y<b.y;
        return x<b.x;
    }
};
multiset<point>p;
int main()
{
    int t,kase=0;
    scanf("%d", &t);
    while(t--)
    {
        p.clear();
        vector<int>ans;
        int n;
        scanf("%d", &n);
        For(i,1,n)
        {
            point temp;
            scanf("%d%d", &temp.x,&temp.y);
            multiset <point>::iterator it=p.lower_bound(temp);
            if(it==p.begin()||(--it)->y>temp.y)
            {
                p.insert(temp);
                it=p.upper_bound(temp);
                while(it!=p.end()&&it->y>=temp.y)p.erase(it++);
            }
          //  printf("%d\n", p.size());
          int len=p.size();
          ans.push_back(len);
        }
        if(kase!=0)printf("\n");
        printf("Case #%d:\n", ++kase);
        For(i,0,n-1)printf("%d\n",ans[i]);
        //printf("\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值