基础:
set是关联容器,set中每个元素的值都是唯一的,系统能够根据元素的值自动进行排序。set中数元素的值并不能直接被改变。STL中还有一些标准关联容器multiset、map 和 multimap 等,这些关联容器内部均是采用红黑树实现的。
set特点:
①、map和set的插入删除效率比其他序列容器高。
原因:set中所有元素都是以节点的方式来存储的,其节点结构和链表类似,指向父节点和子节点。所以,在插入和删除时不需要做内存拷贝和内存移动,故而提高了效率。
②、每次insert之后,以前保存的iterator不会失效。
原因:迭代器iterator在set中就相当于指向节点的指针,只要内存不变,那这个iterator就不会失效。相对于vector来说,每一次的删除和插入之后,指针都有可能失效,调用push_back在尾部插入的时候情况也是如此。因为为了保证内部数据的连续存放,iterator指向的那块内存在插入和删除的过程中可能已经被其他内存覆盖或者内存已经被释放掉了。即使是push_back的时候,容器内部空间可能不够,需要一块新的更大的内存,只能把以前的内存释放掉,申请更大的内存,复制已有的数据元素都新的内存中,最后把需要插入的元素放到最后,那么以前的内存指针自然就不可用了。特别是在和find、erase等操作一起使用的时候,一定要注意:不要使用失效的iterator。
使用方法:
begin() 返回set容器的第一个元素
end() 返回set容器的最后一个元素
clear() 删除set容器中的所有的元素
empty() 判断set容器是否为空
max_size() 返回set容器可能包含的元素最大个数
size() 返回当前set容器中的元素个数
rbegin 返回的值和end()相同
rend() 返回的值和rbegin()相同
其他的一些用法:
①、count():用来查找set中某个某个键值出现的次数。这个函数在set并不是很实用,因为一个键值在set只可能出现0或1次,这样就变成了判断某一键值是否在set出现过了。
②、equal_range():返回一对定位器,分别表示第一个大于或等于给定关键值的元素和第一个大于给定关键值的元素,这个返回值是一个pair类型,如果这一对定位器中哪个返回失败,就会等于end()的值。
③、erase(iterator):删除定位器iterator指向的值
erase(first,second):删除定位器first和second之间的值
erase(key_value):删除键值key_value的值
[注]:set中的删除操作是不进行任何的错误检查的,比如定位器的是否合法等等,所以用的时候自己一定要注意。
④、find():返回给定值值得定位器,如果没找到则返回end()。
⑤、insert(key_value); 将key_value插入到set中 ,返回值是pair<set<int>::iterator,bool>,bool标志着插入是否成功,而iterator代表插入的位置,若key_value已经在set中,则iterator表示的key_value在set中的位置。
inset(first,second);将定位器first到second之间的元素插入到set中,返回值是void.
⑥、lower_bound(key_value) ,返回第一个大于等于key_value的定位器
upper_bound(key_value),返回最后一个大于等于key_value的定位器
set和multiset、unordered_set的区别:
①、multiset是不去重的,set是去重的;
②、unordered_set是C++11中引入的新的容器,其内部不再采用红黑树实现,而是采用了hash表,加速了检索速度。
③、set和map的内部实现是一样的,unordered_set和unordered_map的内部实现也是一样的。
例题:
ACM-ICPC 2018 徐州赛区网络预赛 G Trace
#include<bits/stdc++.h> using namespace std; typedef long long ll; struct point{ int x,y; bool operator < (const point & _point)const{ return x < _point.x; } }tot[50005]; set<point> M; int n,a,b; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d",&tot[i].x,&tot[i].y); } M.clear(); ll ans = 0; ans += tot[n].x;ans += tot[n].y; M.insert(tot[n]); for(int i=n-1;i>=1;i--) { if(M.lower_bound(tot[i])==M.end()){ set<point>::iterator it = M.end(); it--; point temp = *(it); ans += tot[i].y; ans += tot[i].x - temp.x; } else if(M.lower_bound(tot[i])==M.begin()){ point temp = *M.begin(); ans += tot[i].x; ans += tot[i].y - temp.y; } else{ set<point>::iterator it = (M.lower_bound(tot[i])); point temp1 = *it; it--; point temp = *it; ans += tot[i].y - temp1.y; ans += tot[i].x - temp.x; } M.insert(tot[i]); } cout<<ans<<endl; }