题目大意:有n个人,每个人有两个属性x,y,如果对于一个人P(x,y),不存在另外一个人(a,b),使得a<x, b <= y 或者 a < = x, b < y, 则这个人是有优势的。
动态插入每个人,要求统计当前已经插入的人中, 有优势的人的个数。
注意可能出现2个人的x,y都相等的情况,即重复。
思路:用二叉树保存已插入而且有优势的人的信息。先按x小的排,再按y小的排, 把每个人看成一个点操作。
插入操作:当我们要插入一个点p时, 先判断其是否有优势, 若有则插入,没有则跳过。 判断其是否有优势: 找到与其最接近的2个点(lower_bound找出其中一个点),比较点p左边的点和点p的y值的大小即可。
删除操作:对于一个点的插入可能引起其它点的优势失去,所以要删除这些点, 我们可以从第一个比它大的点开始找(之前的点一定是有优势的,用upper_bound找出这个点),往后删除失去优势的点。
插入总体复杂度 O(n * log (n) ), 由于失去优势的点在以后的操作中不可能再有优势,所以删除总体复杂度 O(n * log(n))。
#include <cstdio>
#include <algorithm>
#include <set>
using namespace std;
struct point{
int x, y;
bool operator < (const point &t) const{
return x < t.x || (x == t.x && y <t.y);
}
};
multiset <point> s;
multiset <point>::iterator it;
int main(){
int i, j, cas, n;
scanf("%d", &cas);
for(int ca = 1; ca <= cas; ca++){
scanf("%d", &n);
int x, y;
s.clear();
printf("Case #%d:\n", ca);
while(n--){
scanf("%d%d", &x, &y);
point p = (point) {x, y};
it = s.lower_bound(p);
if(it == s.begin() || (--it)->y > y){
s.insert(p);
it = s.upper_bound(p);
while(it != s.end() && it->y >= y)
s.erase(it++);
}
printf("%d\n", s.size());
}
if(ca != cas) puts("");
}
return 0;
}