以前没怎么用过set,然后挂训练赛的时候发现set的妙用,结合网上用法一边学一边写.

首先set是一种容器,可以跟其他STL容器一样用 set<int > s 来定义, 它包含在STL头文件#include<set>中.

其内部是用红黑树来实现的, 一个是保证set里面是有序的, 默认的排序是从小到大排序, 而且set容器的元素都是唯一的, 如果里面的元素允许重复那就用 multiset 容器来实现.

1. set的常用操作

s.begin()     返回set容器的第一个元素的位置(第一个迭代器)

s.end()       返回set容器的最后一个元素的位置(最后一个迭代器)

s.clear()     清空set容器

s.empty()     判断set容器是否为空

s.insert()    插入一个元素

s.erase()     删除一个元素

s.size()      返回容器里面有多少个元素

s.max_size()  返回set容器可以包含的元素最大个数
实例:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
set<int> s;
int main(int argc, char * argv[]){
s.clear();
if(s.empty()) cout<<"容器是空的"<<endl;
else cout<<"容器不是空的"<<endl;
s.insert();
s.insert();
s.insert();
cout<<"set的第一个值为:"<<*s.begin()<<endl;
cout<<"set的最后一个值为:"<<*s.end()<<endl;
cout<<"set的maxsize的值为:"<<s.max_size()<<endl;
return ;
}

运行结果:

2. set的count() 函数

count() 用来查找set中某个值出现的次数, 但是由于set不允许出现重复的元素, 所以在set中用 s.count() 只会返回0或者1, 可以用来判断需要查找的数在set中存不存在, 而在multiset中就可以统计一个数字的出现个数了.

实例:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
set<int> s1;
multiset<int> s2;
int main(int argc, char * argv[]){
s1.insert();
s1.insert();
s1.insert();
s1.insert();
s2.insert();
s2.insert();
s2.insert();
s2.insert();
cout<<"set中1出现的次数:"<<s1.count()<<endl;
cout<<"set中2出现的次数:"<<s1.count()<<endl;
cout<<"multiset中1出现的次数:"<<s2.count()<<endl;
cout<<"multiset中2出现的次数:"<<s2.count()<<endl;
return ;
}

运行结果:

3.删除元素

s.earse(iterator)      删除iterator指向的值

s.earse(a,b)            删除定位器a和b之间的值

s.earse(key_value)      删除键值key_value的值

实例:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
set<int> s;
int main(int argc, char * argv[]){
set<int>::iterator it;
set<int>::iterator a;
set<int>::iterator b;
for(int i=;i<=;i++){
s.insert(i);
}
cout<<"删除之前set中的元素是:"<<endl;
for(it=s.begin();it!=s.end();it++){
cout<<*it<<" ";
}
cout<<endl;
s.erase(s.begin()); //删除指向的值
cout<<"第一次删除之后set中的元素是:"<<endl;
for(it=s.begin();it!=s.end();it++){
cout<<*it<<" ";
}
cout<<endl;
a=s.begin();
cout<<"a指向的值是:"<<*a<<endl;
b=s.begin();
b++,b++,b++;
cout<<"b指向的值是:"<<*b<<endl;
s.erase(a,b); //删除(a,b)之间的值,a和b都是迭代器
cout<<"第二次删除之后set中的元素是:"<<endl;
for(it=s.begin();it!=s.end();it++){
cout<<*it<<" ";
}
cout<<endl;
s.erase(); //删除值
cout<<"第三次删除之后set中的元素是:"<<endl;
for(it=s.begin();it!=s.end();it++){
cout<<*it<<" ";
}
cout<<endl;
return ;
}

运行结果:

可以发现用第二种方法删除的值是 从a到b, 这里是包含a指向的元素而不包含b指向的元素, 就是 [a,b). 同时set中的删除操作是不会进行错误检查的, 比如定位器是否合法等等,所以用的时候要注意.

4.查找元素

前面说过用count()可以进行元素的查找, 还有一个函数find()也可以进行元素查找

count()可以查找元素存不存在,而find()可以找到元素的位置, 但是如果没有找到就返回end().

实例:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
set<int> s;
int main(int argc, char * argv[]){
set<int>::iterator it;
for(int i=;i<=;i++){
s.insert(i);
}
cout<<"容器中的元素有:"<<endl;
for(it=s.begin();it!=s.end();it++){
cout<<*it<<" ";
}
cout<<endl;
int a;
cout<<"请输入要查找的元素:"<<endl;
while(cin>>a){
if(s.find(a)==s.end()) cout<<"没有找到该元素"<<endl;
else cout<<*s.find(a)<<endl;
}
return ;
}

运行结果:

5. s.lower_bound(key_value)    返回第一个大于等于key_value的定位器

  s.upper_bound(key_value)    返回第一个大于key_value的定位器

  这两个函数都是用二分来实现查找的,所以比较快.

实例:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
set<int> s;
int main(int argc, char * argv[]){
set<int>::iterator it;
s.insert();
s.insert();
s.insert();
s.insert();
s.insert();
s.insert();
s.insert();
cout<<"容器中的元素有:"<<endl;
for(it=s.begin();it!=s.end();it++){
cout<<*it<<" ";
}
cout<<endl;
int a;
cout<<"请输入要查找的元素:"<<endl;
while(cin>>a){
if(s.lower_bound(a)==s.end()) cout<<"找不到这个数"<<endl;
else cout<<"第一个大于等于该值的数是:"<<*s.lower_bound(a)<<endl;
if(s.upper_bound(a)==s.end()) cout<<"找不到这个数"<<endl;
else cout<<"第一个大于该值的数是:"<<*s.upper_bound(a)<<endl;
}
return ;
}

运行结果:

这里注意到,如果在lower_bound和upper_bound中找不到比key_value大的时候, 那么就会返回 s.end()这个迭代器位置.

再来看看set在题目中的用法:

http://codeforces.com/problemset/problem/658/B  

题意: 给定一组数n以及长度为k的容器, 有q个操作.

   1 x: 将x插入容器中

   2 x:查询x是否在容器中,在则输出YES,不在则输出NO

容器中的东西要满足保存的一定是最大的k个值, 比如k=3, 容器中有 1,4,6; 如果插入5的话容器里面就有4,5,6, 再插入3的话容器依然是 4,5,6

n和q都是15000

题解:这就是set的直接用法, 插入值能保证里面的顺序, 然后每次插入让新值与最小的值判断, 也就是s.begin(), 如果大于容器最小值, 则删除容器里面的最小值, 插入新值, 否则不用改变

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=;
struct node{
ll id,c;
}a[N];
set<ll> s;
int main(int argc, char * argv[]){
ll n,k,q;
cin>>n>>k>>q;
for(int i=;i<=n;i++){
cin>>a[i].c;
a[i].id=i;
}
while(q--){
ll op,x;
cin>>op>>x;
if(op==){
if(s.size()<k){
s.insert(a[a[x].id].c);
}
else{
ll ccc=*s.begin();
if(a[a[x].id].c>ccc){
s.erase(s.begin());
s.insert(a[a[x].id].c);
}
}
}
else if(op==){
if(s.count(a[a[x].id].c)==) cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
}
return ;
}

STL容器set用法以及codeforces 685B的更多相关文章

  1. C++ STL容器——stack用法介绍

    stack是一种容器适配器,专门设计用于在LIFO上下文中操作(后进先出),其中元素仅从容器的一端插入和删除. 容器适配器,而不是一种容器. 它是容器适配器是指,只要支持一系列方法的容器(empty, ...

  2. STL容器-- forward_list 用法

    http://www.cplusplus.com/reference/forward_list/

  3. 史上最全的各种C++ STL容器全解析

    史上最全的C++ STL 容器大礼包 为什么\(C++\)比\(C\)更受人欢迎呢?除了\(C++\) 的编译令人感到更舒适,\(C++\)的标准模板库(\(STL\))也占了很重要的原因.当你还在用 ...

  4. c++ stl容器set成员函数介绍及set集合插入,遍历等用法举例

    c++ stl集合set介绍 c++ stl集合(Set)是一种包含已排序对象的关联容器.set/multiset会根据待定的排序准则,自动将元素排序.两者不同在于前者不允许元素重复,而后者允许. 1 ...

  5. 【STL容器学习】-关联容器与map的用法

    STL提供了4个关联容器:set.multiset.map和multimap.这些容器提供了通过keyword高速存储和訪问数据元素的能力.Set和map不同意有反复keyword,而multiset ...

  6. vector容器的用法

    转自一篇博客^-^: 1 基本操作 (1)头文件#include<vector>. (2)创建vector对象,vector<int> vec; (3)尾部插入数字:vec.p ...

  7. STL容器删除元素的陷阱

    今天看Scott Meyers大师的stl的用法,看到了我前段时间犯的一个错误,发现我写的代码和他提到错误代码几乎一模一样,有关stl容器删除元素的问题,错误的代码如下:std::vector< ...

  8. STL容器之优先队列(转)

    STL容器之优先队列 原地址:http://www.cnblogs.com/summerRQ/articles/2470130.html 优先级队列,以前刷题的时候用的比较熟,现在竟然我只能记得它的关 ...

  9. STL容器之优先队列

    STL容器之优先队列 优先级队列,以前刷题的时候用的比较熟,现在竟然我只能记得它的关键字是priority_queue(太伤了).在一些定义了权重的地方这个数据结构是很有用的. 先回顾队列的定义:队列 ...

随机推荐

  1. javabean 深拷贝

    <!-- https://mvnrepository.com/artifact/uk.com.robust-it/cloning --> <dependency> <gr ...

  2. [原创] delphi Memo 滚动到底部/开始 [Delphi XE、Delphi 7]

    以前控制Memo滚动到底部的操作: SendMessage(memo1.Handle,WM_VSCROLL,SB_BOTTOM,0); 或者 Memo1.SelLength:=Length(Memo1 ...

  3. 2019.7.3模拟 七星连珠(行列式+随机+k进制FWT)

    题目大意: 给一个\(n*n\)的矩阵,对于所有排列p,记录\(a[i][p[i]]\)的k进制下不进位加法的结果,问所有被记录过的数. \(n<=50,p=2.3,0<=a[i][j]& ...

  4. spring mvc hibernate spring 整合的增删改查+后台校验+bootstrap

    整合之前先知道大概的思路,首先要知道每个框架的重点要点. 1.首先我们从数据库开始 --创建数据库 create database gs --创建表 create table food ( id ,) ...

  5. thinkphp sql解析缓存

    除了查询缓存之外,ThinkPHP还支持SQL解析缓存,因为ThinkPHP的ORM机制,所有的SQL都是动态生成的,然后由数据库驱动执行. 直线电机厂家 所以如果你的应用有大量的SQL查询需求,那么 ...

  6. NX二次开发-UFUN打开信息窗口UF_UI_open_listing_window()

    NX9+VS2012 #include <uf.h> #include <uf_ui.h> UF_initialize(); //方法1(uc1601) uc1601();// ...

  7. NX二次开发-UFUN拾取向量对话框UF_UI_specify_vector

    #include <uf.h> #include <uf_ui.h> UF_initialize(); //拾取向量对话框 ], pnt[]; int mode = UF_UI ...

  8. shell得到两个文件的差集

    第一种方法: grep: [root@hdp05 src]# grep -vxFf leadering.txt leaderNum.txt [root@hdp05 src]# cat leaderin ...

  9. 第四天:语句、表达式与if分支、循环语句

    表达式 代码风格 代码格式指南 PEP8 缩进4空格 一行不超过79 空行 赋值语句 基本 (x,y) = (5,10) x [x,y,z] = [1,2,3] x a,b,c = 'uhk' a 5 ...

  10. HTML_标签

    <!--HTML:1.概念:最基础的网页开发语言Hyper Text Markup Language 超文本标记语言超文本:超文本是用超链接的方法,将各种不同空间的文字信息组织在一起的网状文本. ...