STL-#include<set>
是一个神奇的会自动排序的容器。然而貌似用起来好复杂(趴)
包含两个容器。
set和multiset。前者为有序集合,后者为有序多重集。set的元素并不能重复,后者可以包含若干个相等的元素。
内部实现是一棵红黑树,他们支持函数基本相同。
声明
set<int> s; set<my_struct> s; multiset<double> s;
set和multiset存储的元素必须定义“小于号”运算符。
重载小于号运算符
c++中内置的int,string类型本身就可以比较大小。如果比较结构体类型,则需要重载"<"运算符。
#include<iostream> using namespace std; struct poi{ int id; double x,y; }; bool operator <(const poi &a,const poi &b) { return a.x<b.x; }
这段代码实现了根据x坐标进行从小到大的小于号重载。
支持函数
size/empty/clear
与其他常用容器相同,分别返回元素个数,是否为空,清空。前两者的复杂度为O(1)
迭代器
set 和 multiset的迭代器被称为“双向访问迭代器”,不支持“随机访问”,支持星号"*"解除引用。仅支持"++","--"两个与算数有关的操作。
设it为一个迭代器,例如:
set<int>::iterator it;
若是把it++,则it会指向下一个元素。这里的“下一个”是指在元素从小到大排序的结果中,排在it下一名的元素。“--”运算同理,指向排在上一个的元素。
执行‘++’‘--’操作时间复杂度都是O(log n)。
begin/end
返回集合的首、尾迭代器,时间复杂度O(1)
s.begin()指向集合中最小的元素的迭代器
s.end()指向集合中最大元素的下一个位置的迭代器
--s.end()指向集合中最大元素的迭代器
insert
s.insert(x)把一个元素x插入到集合s中,时间复杂度O(log n)
在set 中,如果元素已经存在,那么不会重复插入,对集合的状态并无影响。
下面展示一段把n个整数插入有序多重集multiset,并从小到大输出,时间复杂度为O(n log n),相当于进行了一次排序。假设这n个数目前在数组a[1~n]之中。
multiset<int> s; for(int i=1;i<=n;i++){ s.insert(a[i]); } for(multiset<int>::iterator it=s.begin();it!=s.end();it++){ cout<<*it<<endl; }
find
s.find(x)在集合s中查找等于x的元素,并返回指向该元素的迭代器。若不存在,则返回s.end()。时间复杂度为O(log n)
lower_bound/upper_bound
和find差不多,但是条件不太一样。时间复杂度O(log n)
s.lower_bound(x)查找>=x 的元素中最小的一个,并返回指向该元素的迭代器。
s.upper_bound(x)查找>x的元素中最小的一个,并返回指向该元素的迭代器。
注意:当不存在逻辑返回元素时,则返回s.end();
erase
设it是一个迭代器,s.erase(it)从s中删除迭代器it指向的元素,时间复杂度为O(log n)。
设x是一个元素,s.erase(x)会从s中删除所有等于x的元素,时间复杂度为O(k+log n),其中k为被删除元素的个数。
如果想从multiset中删除最多一个等于x的元素,可以这样写:
if((it=s.find(x))!=s.end()){ s.erase(it); }
count
s.count(x)返回集合s中等于x的元素个数,时间复杂度为O(k+log n),其中k为元素x的个数。
在题目中的show time
//update 2019.6.4 创建文档,暂未使用