Efficient Solutions(UVA 11020,erase(it++))

Efficient Solutions(UVA 11020)

注意一点 stl.erase(it++),如果迭代器it写到外面会出错。用迭代器清除时一定要注意这点。。写在里面,写在里面,写在里面。

题目描述
The princess of Centauri Prime is the galaxy’s most eligible bachelorette of the year. She has hopeful
grooms lined up in front of the royal palace for a chance to spend 5 minutes to try and impress her.
After 5 minutes, the gentleman is carried out of the royal chambers by the palace guards, and the
princess makes a decision. She rates the lad on his lineage and charm by giving him a score for each of
the two properties. On Centauri Prime, low scores are better than high scores.
Suppose that she observes two gentlemen - A and B. She assigns A the scores LA and CA (for
lineage and charm, respectively). B receives scores LB and CB. Then A is dominated by B if either
• LB < LA and CB ≤ CA, or
• LB ≤ LA and CB < CA.
In other words, if at least one of B’s scores is better than A’s, and the other score is not worse. She
considers a gentleman to be efficient (or Pareto-optimal) if she has not yet met any other gentleman who
dominates him. She maintains a list of efficient grooms and updates it after each 5-minute presentation.
Given the queue of bachelors and the scores assigned to them by the princess, determine the number
of entries in the list of efficient grooms after each performance.
输入
The first line of input gives the number of cases, N (0 < N < 40). N test cases follow.
Each one starts with a line containing n (0 ≤ n ≤ 15000) — the size of the queue. The next n lines
will each contain two scores (integers in the range [0, 109]). Initially, the list is empty.
输出
For each test case, output one line containing ‘Case #x:’ followed by n lines, line i containing the size
of the list of efficient grooms after the i-th update. Print an empty line between test cases.
样例输入
4
1
100 200
2
100 200
101 202
2
100 200
200 100
5
11 20
20 10
20 10
100 20
1 1
样例输出
Case #1:
1
Case #2:
1
1
Case #3:
1
2
Case #4:
1
2
3
3
1

题目大意
有n个人,每个人有两个属性x和y。如果对于一个人P(x,y),不存在另外一个人(x1,y1),使得 x1<x&&y1<=y 或 x1<=x&&y1<y 的话,那么我们说P是有优势的。每次给出一个人的信息,要求输出在只考虑当前已获得的信息的前提下,多少人是有优势的?
思路
下面分3步来解决本题。
1.如果现在有10个都有优势的人按x坐标顺序放在二维平面上,将是什么样的图形?
随着x坐标越来越大,y坐标将越来越小。因为一个人有优势就说明了不存在任何其他人比这个人绝对的小。所以有优势人的左下角是不会存在点的。整个图像构成了一条凹的曲线且相同的人重叠于一个点上。
2.如果一个人现在是有优势的(其左下角没有点),之后可能失去优势(其左下角插入点),且如果这个人失去优势后,便再也不会重新获得优势了(因为其左下角将永远有某个/些点)。
所以我们可以动态的维护这个优势人群集合,每次插入一个点后,判断该点是否可以插入(是否有优势),然后如果能插入该点,还要删除(因为插入这个点而)失去优势的其他所有点。
3.如何判断一个新点是否可插入(有优势),且如何找到(因为插入新点而)应该被删除的失去优势的点?
将所有点按x优先,y其次的顺序排好序后。对于点P,能否插入P只要看lower_bound(p)- 1这个位置的点的y坐标是否>p.y。只有大于时,才能插入。(自己画图验证一下)
如果插入了点p,那么应该删除包括upper_bound(p)在内的之后的所有的那些y坐标>=p.y的点。(这些点是连续的,只要出现一个点的y<p.y,那么就可以不要再继续删除了)
看懂思路后就很好写了,主要还是要注意stl.erase(it++),it写到里面。考虑lower_bound可能会返回stl.end()
代码如下

#include<bits/stdc++.h>
#define mem(a,x) memset(a,x,sizeof(a))
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long ll;
typedef unsigned long long ull; // %llu
const double PI = acos(-1.0);
const double eps = 1e-6;
const int mod=1e9+7;
const int INF = -1u>>1;
const int maxn = 1e5+5;
struct node
{
    int x,y;
    friend bool operator < (const node a,const node b)
    {
        if(a.x==b.x)
            return a.y<b.y;
        return a.x<b.x;
    }
};
int main()
{
    int Time=0;
    int T;
    cin>>T;
    while(T--)
    {
        int n,ans=0;
        multiset<node>stl;
        multiset<node>::iterator it;
        cout<<"Case #"<<++Time<<":"<<endl;
        cin>>n;
        for(int i=1; i<=n; i++)
        {
            int x,y;
            cin>>x>>y;
            it=stl.lower_bound(node{x,y});
            if(it==stl.begin()||(--it)->y>y)        //左下角不存在点时可以放入
            {
                stl.insert(node{x,y});
                it=stl.upper_bound(node{x,y});      //寻找大于该点的位置
                while(it!=stl.end()&&it->y>=y)      //删除y坐标大于该点坐标的元素(因为此时it->x必大于x)
                {
                    stl.erase(it++);            //注意迭代器要写到里面
                    //     it++;
                }
            }
            cout<<stl.size()<<endl;         //输出元素个数
        }
    }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值