题意:
给你N个人,每个人有两个权值,x,y对于某一个人,如果不存在某一个人x' y',
x' < x && y' <= y 或者x' <= x && y' < y那么这个人就是优势人群,对于输入的这n个人,每输入一个人的时候就输出一次当前这个人加入之后的当前优势人群数量。
思路:
可以在一个二维坐标系上找到规律,所有人都可以映射到二维坐标系上的某一个点,对于任意两个人不同的人(x,y都相等看成一个人)来说,如果他俩都是优势人群,那么他俩肯定存在这样的关系 x < x' && y > y',这样就在坐标系上形成了一个递减的线,还有就是在加人的过程中一定要记住,如果这个人在某一步不属于优势人群,那么他以后就不可能再是优势人群中的了,然后考虑每次增加一个人,有两种情况,(1)当前这个人不是优势人群,那么直接不做任何操作,判断方法比较简单,可以直接找到"大于等于"他的的第一个数的前一个,如果这个数的y比他小,那么就直接断定当前这个人不是优势人群。(2)就是加入当前这个人是优势人群,那么就直接先把这个人加到multiset中,加入之后可能吧别的人变成非优势群体,然后我们在找到"大于"当前这个人的第一个人开始,一直往后,如果y是大于等于当前这个人的,那么直接删除。
**如果a能淘汰b,b能淘汰c,那么a也一定能淘汰c,所以如果直接淘汰b不会影响淘汰c的
提示:
(1) 这里的大于等于只是位置上区分的(排序位置是x小的或者x相等y小的在前面)。
(2) 用multiset(可重集)的原因是可能有多个人x,y同时相等
(3) 如果不懂的话建议在二维坐标上模拟下,还有就是考虑下(1,2)(1,2)(1,2)(1,3)这样的数据,有利于理解二级排序。
(4)*.lower_bound 大于等于的第一个数
(5)*.upper_bound 大于的第一个数
#include<set>
#include<stdio.h>
using namespace std;
typedef struct NODE
{
int x ,y;
friend bool operator < (NODE a ,NODE b)
{
return a.x < b.x || a.x == b.x && a.y < b.y;
//这个地方自己目前有不理解的地方,就是我之前写的优先队列的姿势在结合本体
// 应该是应该是return a.x > b.x || a.x == b.x && a.y > b.y;
//没有正式的学过C++所以..
}
}NODE;
multiset<NODE>myset;
multiset<NODE>::iterator it;
int main ()
{
int t ,cas = 1 ,i ,x ,y ,n;
NODE now;
scanf("%d" ,&t);
while(t--)
{
printf("Case #%d:
" ,cas ++);
scanf("%d" ,&n);
myset.clear();
for(i = 1 ;i <= n ;i ++)
{
scanf("%d %d" ,&x ,&y);
now.x = x ,now.y = y;
it = myset.lower_bound(now);
if(it == myset.begin() ||(--it)->y > y)
{
myset.insert(now);
it = myset.upper_bound(now);
while(it != myset.end() && it -> y >= y)
myset.erase(it++);
}
printf("%d
" ,myset.size());
}
if(t) printf("
");
}
return 0;
}