set/multiset
set容器中所有元素都会在插入时自动排序,默认情况下对元素按关键字自动进行升序排序。
set——相同元素只能有一个
multiset——相同元素可以有多个
底层结构由二叉树实现。
构造:
set<int> s; //默认构造函数
multiset<int> s; //默认构造函数
set(const set &s); //拷贝构造函数
set<int> s2(s); //拷贝构造函数
特点:
所有元素插入时候自动被排序,且不能插入重复值。(去重+排序)
操作:
操作 | 函数 |
---|---|
插入元素 | s.insert(元素); |
删除set容器中的所有的元素 | s.clear() |
判断set容器是否为空 | s.empty() |
返回当前set容器中的元素个数 | s.size() |
查找set中某个某个键值出现的次数(是否出现) | s.count(键值) |
返回给定值的定位器,如果没找到则返回end() | s.find() |
返回迭代器,指向第一个大于等于key_value的元素 | lower_bound(key_value) |
返回迭代器,指向第一个大于key_value的元素 | upper_bound(key_value) |
返回迭代器,引用当前容器的第一个元素 | s.begin() |
返回迭代器,引用当前容器的最后一个元素 | s.end() |
返回迭代器,引用当前容器的最后一个元素 | s.rbegin() |
返回迭代器,引用当前容器的第一个元素前面的位置 | s.rend() |
删除:
s.erase() | 操作 |
---|---|
s.erase(iterator) | 删除定位器iterator指向的值 |
s.erase(first,second) | 删除定位器first和second之间的值(左闭右开) |
s.erase(key_value) | 删除键值key_value的值 |
遍历:
以遍历输出集合元素为例。
void printset()
{
for(set<int>::iterator it=s.begin();it!=s.end();it++)
{
cout<<*it<<endl;
}
}
参考:https://www.cnblogs.com/wkfvawl/p/11041079.html
练习:
明明的随机数-set
#include <bits/stdc++.h>
using namespace std;
int n,x,k;
set<int> s;
int main()
{
while(cin>>n)
{
s.clear();
for(int i=1;i<=n;i++)
{
cin>>x;
s.insert(x);
}
k=0;
printf("%d\n",s.size());
set <int>::iterator it;
for(it=s.begin();it!=s.end();it++)
{
k++;
if(it==s.begin()) printf("%d",*it);
else printf(" %d",*it);
}
printf("\n");
}
return 0;
}
第K小整数-SET
#include <bits/stdc++.h>
using namespace std;
int n,x,k,p;
set<int> s;
int main()
{
cin>>n>>p;
s.clear();
for(int i=1;i<=n;i++)
{
cin>>x;
s.insert(x);
}
k=0;
if(s.size()<p||p==0)
printf("NO RESULT");
else
{set <int>::iterator it;
for(it=s.begin();it!=s.end();it++)
{
k++;
if(k==p) printf("%d\n",*it);
}
}
return 0;
}
单词记忆-set-map
#include <bits/stdc++.h>
using namespace std;
int n,x,k,p;
string a;
set<string> s;
int main()
{
cin>>n;
while(n--)
{
cin>>x;
if(x==0)
{
cin>>a;
s.insert(a);
}
if(x==1)
{
cin>>a;
if(s.count(a)) printf("YES\n");
else printf("NO\n");
}
}
return 0;
}
列车调度-SET
#include <bits/stdc++.h>
using namespace std;
int n,x,k,p;
set<int> s;
int main()
{
cin>>n;
p=1;
while(n--)
{
cin>>x;
if(s.empty()) s.insert(x);
else
{
set <int>::iterator k;
k=s.lower_bound(x);
if(x>*k)
{s.insert(x);
p++;}
else
{
s.erase(*k);
s.insert(x);
}
}
}
printf("%d\n",p);
return 0;
}
相似的数集简单版-SET
set去重
当然这个题也可以用数组思想
#include <bits/stdc++.h>
using namespace std;
int n,k,m,x,y,b;
set <int> p[55];
int main()
{
cin>>n;
for(int j=1;j<=n;j++)
{
cin>>m;
for(int i=1;i<=m;i++)
{
cin>>b;
p[j].insert(b);
}
}
cin>>k;
while(k--)
{
int nc=0,nt=0;
cin>>x>>y;
for(set<int>::iterator it=p[x].begin();it!=p[x].end();it++)
{
if(p[y].count(*it)) nc++;
}
nt=p[x].size()+p[y].size()-nc;
double ans=((double)nc/nt*1.0)*100;
k==0?printf("%.2lf%%",ans):printf("%.2lf%%\n",ans);
}
return 0;
}
NOIP 题海战-SET-1
此题必须考虑迭代器返还的做法,否则不能ac
详情请看:迭代器失效
https://blog.youkuaiyun.com/weixin_41413441/article/details/81591656
模板写法:
set<int>::iterator it;
for(it=ans.begin(); it!=ans.end(); )
{
if(条件) ans.erase(it++);
else it++;
}
#include <bits/stdc++.h>
using namespace std;
int n,k,m,x,b,p,gs,f;
set <int> s[1005];
set <int> ans,pp;
int main()
{
ios::sync_with_stdio(0);
scanf("%d%d",&n,&m);
for(int j=1; j<=n; j++)
{
scanf("%d",&p);
for(int i=1; i<=p; i++)
{
scanf("%d",&b);
s[j].insert(b);
}
}
for(int i=1; i<=m; i++)
{
pp.insert(i);
}
scanf("%d",&k);
set<int>::iterator it;
for(int j=1;j<=k;j++)
{
int a[1005]={0};
ans=pp;
scanf("%d%d",&x,&gs);
for(int i=1;i<=gs;i++)
{
scanf("%d",&f);
if(a[f]==0)//数组去重
{
a[f]++;
if(x==0)
{
for(it=ans.begin(); it!=ans.end(); )
{
if(s[f].count(*it))
ans.erase(it++);
else it++;
}
}
if(x==1)
{
for(it=ans.begin(); it!=ans.end();)
{
if(s[f].count(*it)==0)
ans.erase(it++);
else it++;
}
}
}
}
for(it=ans.begin(); it!=ans.end(); it++)
{
printf("%d ",*it);
}
printf("\n");
}
return 0;
}