题意
- 给定n个点对(x,y),如果不存在一个点对(a,b),使得(a<=x&&b<y)||(a<x&&b<=y),则称(x,y)是有优势的点对
- 每次加入点对后,输出当前有优势的点对个数
思路
- 点对问题转换成二维坐标系中问题
- 画图发现,有优势的点对应的几何意义是,和坐标轴围成的范围(除自身以外的闭集)不含有其他点
- 用一个容器实现,使该容器对下标进行排序
- 注意:用map和set都会寄,因为无法处理重复点,本题中,两个重复点会都被记录为有优势点、
代码
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++){
int n;
scanf("%d",&n);
printf("Case #%d:\n",i);
multiset<pair<int,int>>mp;
mp.clear();
for(int j=0;j<n;j++){
pair<int,int>a;
scanf("%d%d",&a.first,&a.second);
auto pt1=mp.lower_bound(a);
if(pt1==mp.begin()||a.second<(--pt1)->second){
mp.insert(a);
auto pt2=mp.upper_bound(a);
while(pt2!=mp.end()&&pt2->second>=a.second){
mp.erase(pt2++);
}
}
printf("%d\n",mp.size());
}
printf("\n");
}
return 0;
}
STL注意事项
- map的排序默认按照键升序,可以用greater<>变为降序或者自定义比较函数
map,set,multiset
通用方法
方法 |
描述 |
size() |
返回元素数量 |
empty() |
判断是否为空 |
clear() |
清空容器 |
begin() /end() |
返回迭代器 |
rbegin() /rend() |
返回反向迭代器 |
count(value) |
统计元素出现次数,可用于判断元素是否出现过 |
set/multiset 特有方法
方法 |
描述 |
insert(value) |
插入元素 |
erase(value) |
删除元素 |
find(value) |
查找元素 |
map 特有方法
方法 |
描述 |
operator[] |
访问或插入元素 |
at(key) |
安全访问元素 |
insert({k,v}) |
插入键值对 |
erase(key) |
删除键值对 |
lower_bound和upper_bound
- lower_bound:返回第一个 不小于 目标 pair 的元素
- upper_bound:返回第一个 严格大于 目标 pair 的元素
- upper_bound 会返回严格大,意味着多个元素会先比第一个,如果相同再比较第二个