zoukankan      html  css  js  c++  java
  • STL容器set用法以及codeforces 685B

    以前没怎么用过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(3); s.insert(6); s.insert(1); cout<<"set的第一个值为:"<<*s.begin()<<endl; cout<<"set的最后一个值为:"<<*s.end()<<endl; cout<<"set的maxsize的值为:"<<s.max_size()<<endl; return 0; }

    运行结果:

    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(3);
           s1.insert(6);
           s1.insert(1);
           s1.insert(1);
           s2.insert(3);
           s2.insert(6);
           s2.insert(1);
           s2.insert(1);
           cout<<"set中1出现的次数:"<<s1.count(1)<<endl;
           cout<<"set中2出现的次数:"<<s1.count(2)<<endl;
           cout<<"multiset中1出现的次数:"<<s2.count(1)<<endl;
           cout<<"multiset中2出现的次数:"<<s2.count(2)<<endl;
        return 0;
    }

    运行结果:

     

    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=1;i<=10;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(9); //删除值
           cout<<"第三次删除之后set中的元素是:"<<endl;
           for(it=s.begin();it!=s.end();it++){
               cout<<*it<<" ";
           }
           cout<<endl;
        return 0;
    }

    运行结果:

    可以发现用第二种方法删除的值是 从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=1;i<=10;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 0;
    }

    运行结果:

     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(1);
        s.insert(6);
        s.insert(14);
        s.insert(18);
        s.insert(3);
        s.insert(7);
        s.insert(4);
        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 0;
    }

    运行结果:

     这里注意到,如果在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=150050;
    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=1;i<=n;i++){
               cin>>a[i].c;
               a[i].id=i;
           }
           while(q--){
               ll op,x;
               cin>>op>>x;
               if(op==1){
                   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==2){
                   if(s.count(a[a[x].id].c)==0) cout<<"NO"<<endl;
                   else cout<<"YES"<<endl; 
               }
           }
        return 0;
    }
  • 相关阅读:
    CoreLocation
    通知(NSNotificationCenter)
    加载xib文件
    UITextField
    UIButton
    UILabel
    UIAlertController
    layoutSubviews
    Java AQS详解(转)
    Java中synchronized
  • 原文地址:https://www.cnblogs.com/wushengyang/p/11934329.html
Copyright © 2011-2022 走看看