UVA 11020 Efficient Solutions

 

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1961

题意:依次给出n个点。每个点的优先级为x小的优先级大;x相同的y小的优先级大。维护一个点的数列,使得到目前为止优先级大的都保存在其中(可能有多个同时保存在其中因为可能他们之间是不能比较大小的)。输出每次有新元素插入后的数列中的点的个数(当然新元素插入后要先进行刷新).

思路:设置一个multiset<point>。(1)那么每次有一个新元素p时,我们先判断里面有没有优先级比这个大的,先lower_bound一次找到大于等于p的,设其位置为it,那么(it-1)的y小于等于p的y时p就没有插入的必要了。想想看,(it-1)的优先级是大于p的,也就是x小于p或者x等于p且y小于p的y。那么只有人家的x小于p的x且人家的y大于p的y时,p就不会与其比较大小了,因此才能插入。(2)插入之后,要检测里面有木有比p的优先级小的。首先upper_bound一次找打大于p的,设为it,那么要么it的x大于p要么it的x等于p,但是y大于p(这里不可能出现等于,否则it就等于p了)。那么现在只要it的y大于等于p的y就要删除。因为之后的x都是大于等于it的。


struct point
{
    int x,y;


    point(){}
    point(int _x,int _y)
    {
        x=_x;
        y=_y;
    }


    void get()
    {
        RD(x,y);
    }


    int operator<(const point &a) const
    {
        return x<a.x||x==a.x&&y<a.y;
    }
};


multiset<point> s;
multiset<point>::iterator it;


int n;


int main()
{
    int flag=0,num=0;
    rush()
    {
        if(flag) puts("");
        flag=1;
        RD(n); s.clear();
        point p;
        printf("Case #%d:\n",++num);
        while(n--)
        {
            p.get();
            it=s.lower_bound(p);
            if(it==s.begin()||(--it)->y>p.y)
            {
                s.insert(p);
                it=s.upper_bound(p);
                while(it!=s.end()&&it->y>=p.y) s.erase(it++);
            }
            printf("%d\n",s.size());
        }
    }
    return 0;
}

你可能感兴趣的:(uva)