2020年2月18日 set
set相当于一个自动排序+自动去重的数组,即插入时会自动排序,插入重复元素时不会变化。set的元素访问需要用到迭代器,其原理可以类比普通循环中的循环变量i。
林大OJ 743 明明的随机数-set
set的模版题,set的特点在排序和去重。
#include <bits/stdc++.h>
using namespace std;
set<int>a;
int main()
{
int n,x;
while(cin>>n){
a.clear();
for(int i=1;i<=n;i++){
cin>>x;
a.insert(x);
}
printf("%d\n",a.size());
set<int>::iterator it;
for(it=a.begin();it!=a.end();it++)
it==a.begin()?printf("%d",*it):printf(" %d",*it);
printf("\n");
}
return 0;
}
林大OJ 1684 第K小整数-set
仍然是模版题,看到“相同的数字只计算一次”就用set就对了。
#include <bits/stdc++.h>
using namespace std;
set<int>a;
int main()
{
int n,x,k,cnt,flag;
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>x;
a.insert(x);
}
set<int>::iterator it;
cnt=flag=0;
for(it=a.begin();it!=a.end();it++){
cnt++;
if(cnt==k){
printf("%d\n",*it);
flag=1;
}
}
if(flag==0) printf("NO RESULT\n");
return 0;
}
林大OJ 2117 单词记忆-set-map
在set中查找元素用count函数更简单点,但只能知道有没有,这道题已经足够了。
#include <bits/stdc++.h>
using namespace std;
set<string>a;
int main()
{
int n,f,flag;
string x;
cin>>n;
a.clear();
set<string>::iterator it;
while(n--){
cin>>f>>x;
if(f==0) a.insert(x);
if(f==1){
flag=0;
if(a.count(x)){
printf("YES\n");
flag=1;
}
if(flag==0) printf("NO\n");
}
}
return 0;
}
林大OJ 1680 列车调度-SET
set中的数据存放是有顺序的。
这道题相当于找列车初始顺序中最长单调递减子序列的长度。换言之,如果新的一辆列车的序号大于目前所有轨道上末尾车的序号就要重开一条轨道用来调度。
#include <bits/stdc++.h>
using namespace std;
set<int>a;
int main()
{
ios::sync_with_stdio(false);
int n,num;
cin>>n;
for(int i=1;i<=n;i++){
cin>>num;
if(!a.empty()&&*a.rbegin()>num)
a.erase(*a.upper_bound(num));
a.insert(num);
}
printf("%d\n",(int)a.size());
return 0;
}
林大OJ 2119 相似的数集简单版-SET
利用count函数找到两个数集中相同元素的个数即可,因为要求相同元素两两不同,所以用set。
#include <bits/stdc++.h>
using namespace std;
set<int>a[51];
int main()
{
ios::sync_with_stdio(false);
int m,n,x,n1,n2,k;
cin>>n;
for(int i=1;i<=n;i++){
cin>>m;
while(m--){
cin>>x;
a[i].insert(x);
}
}
cin>>k;
while(k--){
cin>>n1>>n2;
int same=0,dif=0;
set<int>::iterator it;
for(it=a[n1].begin();it!=a[n1].end();it++)
if(a[n2].count(*it)) same++;
dif=a[n1].size()+a[n2].size()-same;
printf("%.2lf%%\n",1.0*same/(1.0*dif)*100.0);
}
return 0;
}
林大OJ 1679 NOIP 题海战-SET-1
题目很长,主要是要读懂题目每句话的意思。
#include <bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int n,m,x,k,num,type;
set<int>s[N],quanji,ans;
set<int>::iterator it;
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>num;
for(int j=1;j<=num;j++){
cin>>x;
s[i].insert(x);
}
}
for(int i=1;i<=m;i++)
quanji.insert(i);
cin>>k;
while(k--){
cin>>type>>num;
ans=quanji;
if(type==0){
for(int i=1;i<=num;i++){
cin>>x;
for(it=ans.begin();it!=ans.end();){
if(s[x].count(*it)) ans.erase(it++);
else it++;
}
}
}
else{
for(int i=1;i<=num;i++){
cin>>x;
for(it=ans.begin();it!=ans.end();){
if(!s[x].count(*it)) ans.erase(it++);
else it++;
}
}
}
for(it=ans.begin();it!=ans.end();it++)
printf("%d ",*it);
printf("\n");
}
return 0;
}
林大OJ 1677 指数序列-set-map
这道题其实是昨天map的压轴题,因为又写着set,所以决定今天解决。这道题其实相当于又回到了二进制的计算上,大佬的题解:
由于2x + 2x = 2x+1,对于一个非降序列,我们可以向上进位得到单调递增序列,如:
1 1 2 3 5——>2 2 3 5——>3 3 5——>4 5
由于2v-1 = 20 + 21 + 22 +……+ 2v-1,所以我们只需暴力找答案的二进制中0的个数。
#include <bits/stdc++.h>
using namespace std;
int n,x,s,mx;
set<int>ans;
map<int,int>vis;
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++){
cin>>x;
vis[x]++;
ans.insert(x);
mx=max(mx,x);
}
set<int>::iterator it;
for(it=ans.begin();it!=ans.end();it++){
x=*it;
int tmp=vis[x];
vis[x]=tmp%2;
if(vis[x]==0) s++;//统计被删除的数的个数
int k=tmp/2;//将相同的两个数合并
if(!vis[x+1]&&k!=0){
ans.insert(x+1);//合并后的数大小+1
mx=max(mx,x+1);//mx记录合并完成后数的最大值
}
vis[x+1]+=k;//合并后数的个数+k
}
printf("%d\n",mx+1-ans.size()+s);
return 0;
}