大一寒假训练十一(set)2020.02.18(7题)

大一寒假训练十一(set)id:536

Problem:A 明明的随机数-set

Description

明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N <= 100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作。

Input

输入数据有多组
每组有2行,第1行为1个正整数,表示所生成的随机数的个数:N
第2行有N个用空格隔开的正整数,为所产生的随机数。

Output

每组输出也是2行,第1行为1个正整数M,表示不相同的随机数的个数。第2行为M个用空格隔开的正整数,为从小到大排好序的不相同的随机数。

Sample Input

10
20 40 32 67 40 20 89 300 400 15

Sample Output

8
15 20 32 40 67 89 300 400

code

#include
using namespace std;
int main()
{
    set<int>num;
    int n,m,x,f;
    while(cin>>n){
        num.clear();
        for(int i=1;i<=n;i++){
            cin>>x;
            num.insert(x);
        }
        cout<<num.size()<<endl;
        set<int>::iterator it;
        for(it=num.begin();it!=num.end();++it){
            if(it==num.begin())
            cout<<*it;
            else cout<<" "<<*it;
        }
        printf("\n");
    }

    return 0;
}

Problem:B第K小整数-SET

Description

现有n个正整数,n≤10000,要求出这n个正整数中的第k个最小整数(相同大小的整数只计算一次),k≤1000,正整数均小于30000。

Input

第一行为n和k; 第二行开始为n个正整数的值,整数间用空格隔开。

Output

第k个最小整数的值;若无解,则输出“NO RESULT”。

Sample Input

10 3
1 3 3 7 2 5 1 2 4 6

Sample Output

3

code

#include
using namespace std;
int main()
{
    set<int>a;
    int n,k,x,f,cnt=0;
    cin>>n>>k;
    while(n--){
        cin>>x;
        a.insert(x);
    }
    if(k>a.size()) cout<<"NO RESULT"<<endl;
    else {
        set<int>::iterator it;
        for(it=a.begin();it!=a.end();++it){
            cnt++;
            if(cnt==k) cout<<*it<<endl;
        }
    }
    return 0;
}

Problem:C 单词记忆-set-map

Description

要英语考试,小雅同学准备考小熊同学英语单词。
会就输出YES
不会就输出NO

Input

输入一个n,(1<=n<=1000)代表要考的单词的个数;
然后每行是一个数字和这个单词;数字为0或1;
0表示记忆单词;
1表示询问单词会还是不会?

Output

对于每个单词的询问,输出YES 或NO

Sample Input

5
0 good
0 red
1 goose
0 goose
1 goose

Sample Output

NO
YES

code

#include
using namespace std;
int main()
{
    set<string>a;
    int n,f;
    string x;
    cin>>n;
    while(n--){
        cin>>f>>x;
        if(f==0) a.insert(x);
        else{
            if(a.count(x)) cout<<"YES"<<endl;
            else cout<<"NO"<<endl;
        }
    }
    return 0;
}

Problem:D 列车调度-SET

Description

两端分别是一条入口(Entrance)轨道和一条出口(Exit)轨道,它们之间有 N 条平行的轨道,如图 10.6-1 所示。每趟列车从入口可以选择任意一条轨道进入,最后从出口离开。在图中有 9趟列车,在入口处按照 {8,4,2,5,3,9,1,6,7} 的顺序排队等待进入。如果要求它们必须按序号递减的顺序从出口离开,则至少需要多少条平行铁轨用于调度?

Input

第 1 行给出 1 个正整数 N,2≤N≤1e5 。
第 2 行给出从 1~N 的正整数序号的一个重排列,数字间以一个空格分隔

Output

输出一行一个数,表示可以将输入的列车按序号递减的顺序调离所需要的最少的铁轨条数。

Sample Input

9
8 4 2 5 3 9 1 6 7

Sample Output

4

Tips

在纸上模拟一下入轨过程,发现每次入轨的车都会跟在第一个大于它的车的后面,如果现有轨道的最后一列车都小于他,则增加轨道
所以说,现有轨道的最后一列车以外的车号都是用不上的,可以入一辆车删一辆车,增加轨道时则不用删
用upper_bound会方便许多

code

#include 
using namespace std;
set<int>s;
set<int>::iterator it;
int n,x,ans=1;
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>x;//列车准备入轨
        if(s.empty())s.insert(x);
        else{
            it=s.upper_bound(x);
            if(it==s.end()){//如果x比set中任何一个数都大,增加轨数
                s.insert(x);
                ans++;
            }
            else{
                s.erase(*it);//*it是第一个大于x的车号
                s.insert(x);//将x放入刚刚好的位置
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}

Problem:E 相似的数集简单版-SET

Description

给出两个数集,它们的相似程度定义为Nc/Nt*100%。其中,Nc表示两个数集中相等的、两两互不相同的元素个数,而Nt表示两个数集中总共的互不相同的元素个数。请计算任意两个给出数集的相似程度。

Input

输入第一行给出一个正整数N(N<=50),是集合的个数。随后N行,每行对应一个集合。每个集合首先给出一个正整数M(M<=5000),是集合中元素的个数;然后跟M个[0, 3000]区间内的整数。
之后一行给出一个正整数K(K<=800),随后K行,每行对应一对需要计算相似度的集合的编号(集合从1到N编号)。数字间以空格分隔。

Output

输出共K行,每行一个保留2位小数的实数,表示给定两个集合的相似度值。

Sample Input

3 
3 99 87 101 
4 87 101 5 87 
7 99 101 18 5 135 18 99 
2 
1 2 
1 3 

Sample Output

50.00% 
33.33%

code

#include
using namespace std;
set<int>a[55];
int n,m,k,x,f,s;
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>m;
        while(m--){
            cin>>x;
            a[i].insert(x);
        }
    }
    cin>>k;
    while(k--){
        cin>>f>>s;//first,second
        set<int>::iterator it;
        int cnt1=0,cnt2;
        for(it=a[f].begin();it!=a[f].end();++it){
            if(a[s].count(*it)) cnt1++;//对于a[f]中每个元素,如果a[s]中存在,cnt++
        }
        cnt2=a[f].size()+a[s].size()-cnt1;
        printf("%.2lf%%\n",1.0*cnt1/cnt2*100.0);
    }
    return 0;
}

Problem:F NOIP 题海战-SET-1

Description

某信息学奥赛教练经验丰富,他的内部题库有 m 道题。他有 n 个学生,第 i 个学生完成了p[i]道题。由于马上要进行 NOIP 的考试,该教练便举行了 k 场比赛和训练,每场比赛式训练都会有一些他的学生参加,但是如何选题令他非常烦恼。对于每场比赛,他要保证所出的题没有任何一道已有任何一个参赛学生做过;而对于每场训练,他要保证所出的所有题都被每一个参赛学生做过。

Input

第 1 行 2 个正整数 n 和 m,表示学生数和题库中的题目总量。
第 2~n+1 行,先是 1 个正整数 p(1<=p<=m),然后 p 个整数表示第 i 个学生的做题记录(可能重复做同一道题)。
第 n+2 行,1 个正整数 k,表示要举行的比赛和训练总数(可能有学生重复报名)。
接下来的 k 行,每行的第 1 个整数 type 表示是训练或者比赛(1 为训练,0 为比赛)。第 2个数 q(1<=q<=n) 表示参赛学生数,然后 q 个正整数表示参赛学生编号。每一行中的两个数之间有一个空格。

数据范围:1<=n,m,k<=1000

Output

共 k 行,每行表示本次训练或比赛可选的题目(由小到大排序,中间用一个空格隔开,注意本题输出格式是每行末尾也有一个空格,如果没有可选的题目输出一个空行)。

Sample Input

5 10
2 3 7
1 3
2 4 7
3 3 6 10
7 1 2 3 4 7 8 9
6
0 3 3 4 5
0 3 1 3 4
1 2 1 3
0 1 5
1 1 2
1 2 3 5

Sample Output

5
1 2 5 8 9
7
5 6 10
3
4 7

code

#include 
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;//选手i做过的题号为x(题目必须去重)
            s[i].insert(x);
        }
    }
    for(int i=1;i<=m;i++)
        quanji.insert(i);//预处理全集
    cin>>k;
    while(k--){
        cin>>type>>num;
        ans=quanji;//两个set之间可以用等于号赋值
        if(type==0){//比赛,他要保证所出的题都没有被任何一个参赛学生做过
            for(int i=1;i<=num;i++){
                cin>>x;//选手编号为x
                for(it=ans.begin();it!=ans.end();){
                    if(s[x].count(*it))ans.erase(it++);//筛掉选手x做过的所有题
                    else it++;
                }
            }
        }
        else{//训练,他要保证所出的题都被每一个参赛学生做过
            for(int i=1;i<=num;i++){
                cin>>x;//选手编号为x
                for(it=ans.begin();it!=ans.end();){
                    if(!s[x].count(*it))ans.erase(it++);//筛掉选手x没做过的所有题
                    else it++;
                }
            }
        }
        for(it=ans.begin();it!=ans.end();it++)
            printf("%d ",*it);
        printf("\n");
    }
    return 0;
}

Problem:G 昨天做过了

总结

1.set的定义

set\<typename\> name;

2.set的常用指令

insert();添加一个元素
erase();移除一个元素
count();判断某个元素是否存在
size();元素个数
clear();清空

3.set中的删除

erase(iterator) ,删除定位器iterator指向的值
erase(first,second),删除定位器first和second之间的值
erase(key_value),删除键值key_value的值

• set<int> s;
• set<int>::const_iterator iter; • set<int>::iterator first;
• set<int>::iterator second;for(int i = 1 ; i <= 200 ; ++i){s.insert(i);}//第一种删除
• s.erase(s.begin());//第二种删除
• first = s.begin();
• second = s.begin();
• second++; second++;
• s.erase(first,second);//第三种删除
• s.erase(18);

4.迭代器的使用

set只能通过迭代器访问。

set<typename>::iterator it;
for(it = s.begin() ; it != s.end() ; ++it) {
 cout<<*it<<" ";
} 

5.其他

lower_bound(key_value) ,返回第一个大于等于key_value的定位器
upper_bound(key_value),返回最后一个大于等于key_value的定位器

你可能感兴趣的:(大一寒假集训)