c++stl之set(集合)

一、set用法总结

1.insert,插入某个数
2.erase,删除某个数,不是迭代器
3.count,判断某个数是否在set中,不是迭代器
4.size,获取元素个数
5.clear,清空集合
6.集合的复制,直接用等号复制
7.set是默认排好序从小到大的,如果想要从大到小,用以下方式定义

set<int, greater<int> >vis;

8.set::iterator it=s.upper_bound(x); //返回s中第一个大于x的迭代器
9.set也有反向迭代器set<int>::reverse_iterator iter;

二、题目总结

1.nefu1679 NOIP 题海战-SET-1

用到一个小技巧:取一个集合,含有1到m的所有元素,再用迭代器遍历这个集合,如果从同学的题库里找到,就删除

#include <bits/stdc++.h>
using namespace std;
set<int>vis[1005],ans,mo;
set<int>::iterator it;
int main()
{
    int n,m,c,x;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&c);
        for(int j=1;j<=c;j++)
        {
            scanf("%d",&x);
            vis[i].insert(x);
        }
    }
    for(int i=1;i<=m;i++)mo.insert(i);
    int k,flag;
    scanf("%d",&k);
    for(int i=1;i<=k;i++)
    {
        ans=mo;
        scanf("%d %d",&flag,&c);//比赛题目要都没做过,
        if(flag==0){//比赛,做过就删除
        for(int j=1;j<=c;j++)
        {
            scanf("%d",&x);
            for(it=ans.begin();it!=ans.end();it++)
            {
                if(vis[x].count(*it))ans.erase(*it);
            }
        }
        for(it=ans.begin();it!=ans.end();it++)
            printf("%d ",*it);
            printf("\n");
        }
        else//
        {
            for(int j=1;j<=c;j++)
            {
                scanf("%d",&x);
                for(it=ans.begin();it!=ans.end();it++)
                {
                    if(!vis[x].count(*it))ans.erase(*it);
                }
            }
            for(it=ans.begin();it!=ans.end();it++)
                printf("%d ",*it);
            printf("\n");
        }
    }
	return 0;
}

2.nefu2119 相似的数集简单版-SET

1.先把每一个集合都放入集合中 2.再遍历一个集合找重合,为分子Nc 3.两个集合大小相加减去重复的即为分母Nt

tip:printf("%%");打印两个百分号可输出一个百分号

#include <bits/stdc++.h>
using namespace std;
set<int>vis[55];
int main()
{
    int n,m,x;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&m);
        for(int j=0;j<m;j++)
        {
            scanf("%d",&x);
            vis[i].insert(x);
        }
    }
    int k,num1,num2;
    scanf("%d",&k);
    while(k--)
    {
        int a=0;
        scanf("%d %d",&num1,&num2);
        set<int>::iterator it;
        for(it=vis[num1].begin();it!=vis[num1].end();it++)
        {
            if(vis[num2].count(*it))a++;
        }
        int b=vis[num1].size()+vis[num2].size()-a;
        printf("%.2lf%%\n",a*1.0/(b*1.0)*100.0);
    }
	return 0;
}

3.nefu1680 列车调度-SET

这道题关键:要发现问题的本质!!(认真脸)

可以先画图模拟,每条路能否进去只与这条路最小的那个数有关,只存入每条路最小的那个火车编号,若比每条路最小的都小,那就只能再增添一条路

进一个,若是最大的数,则进一条空路,若不是最大的数,则把大于他一点的数删掉,把这个数插入

#include <bits/stdc++.h>
using namespace std;
set<int>vis;
set<int>::iterator it;
int main()
{
    int n,cnt=0,x;
    cin>>n;
    while(n--)
    {
        cin>>x;
        if(vis.empty()){cnt++;vis.insert(x);continue;}
        it=vis.upper_bound(x);
        if(it==vis.end()){cnt++;vis.insert(x);}
        else
        {
            vis.insert(x);
            vis.erase(*it);
        }
    }
    cout<<cnt<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhoucheng_123/article/details/104382061