zoukankan      html  css  js  c++  java
  • C++STL小结

    更新日志:

    update on 10.12 

    完善了队列内容

    更新了二分

    (未完待续。。。)
    更新队列:vector,deque,set,bitset,nth_element以及一些神奇函数

    本文同步更新于我的luogu blog

    前言:

    STL是个好东西,可以帮助我们较快的构建程序。

    虽然这玩意儿常数大

    但在时间复杂度正确的情况下,一般不会有人xian de dan teng去卡STL的。

    在本蒟蒻会的前提下整理的,可能不全

    目录:

    sort

    队列&优先队列

    二分(lower_bound&upper_bound)

    正文

    sort 

    这玩意儿应该挺好理解,大佬们把它优化的很好了,一般排序就用它就ok  

    输入:
    10
    5465 12 54 6 21 54 315 1 0 1 

    #include<cstdio>
    #include<algorithm>//sort所在头文件
    
    using namespace std;//sort
    const int N=10005;
    int n,a[N];
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        sort(a+1,a+n+1);
            /*
            a:排序数组名称 
            1:起始下标 
            n:数组长度 
        */
        for(int i=1;i<=n;i++)
        {
            printf("%d ",a[i]);
        }
        return 0;
    } 

    输出
    0 1 1 6 12 21 54 54 315 5465  

    sort排序一般默认为从小到大排,若想要从大到小排,我们可以重定义其中的比较函数,代码如下:

    #include<bits/stdc++.h>
    
    using namespace std;
    const int N=10005;
    int n,a[N];
    bool cmp(int a,int b)
    {
        return a>b;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        sort(a+1,a+n+1,cmp);
            /*
            cmp:比较函数 
            */
        for(int i=1;i<=n;i++)
        {
            printf("%d ",a[i]);
        }
        return 0;
    } 

    输出:
    5465 315 54 54 21 12 6 1 1 0 

    当然,我们也可以根据实际需要对cmp函数做出相应更改:
    如,对结构体排序:

    #include<cstdio>
    #include<algorithm>//sort所在头文件
    
    using namespace std;//sort
    const int N=10005;
    int n;
    struct qwq{
        int x,y;
    };
    qwq a[N],b[N];
    bool cmp(const qwq &a,const qwq &b)
    {
        return a.x==b.x?a.y<b.y:a.x>b.x;
        //以结构体中x为第一关键字降序排列,y升序排列
        /*等价于
        if(a.x==b.x)return a.y<b.y;
        else return a.x>b.y; 
        */     
    }
    bool com(const qwq &a,const qwq &b)
    {
        return a.y==b.y?a.x<b.x:a.y<b.y;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&a[i].x,&a[i].y);
            b[i].x=a[i].x,b[i].y=a[i].y;
        }
        sort(a+1,a+n+1,cmp);
        sort(b+1,b+n+1,com);
            /*
            com,cmp:比较函数 
            */
        printf("
    ");
        for(int i=1;i<=n;i++)
        {
            printf("%d %d
    ",a[i].x,a[i].y);
        }
        printf("
    ");
        for(int i=1;i<=n;i++)
        {
            printf("%d %d
    ",b[i].x,b[i].y);
        }
        return 0;
    } 
    /*输入:
    10
    3 5
    9 8
    4 6
    1 0
    3 8
    6 1
    2 2
    8 5
    1 9
    7 2
    
    a数组输出: 
    9 8
    8 5
    7 2
    6 1
    4 6
    3 5
    3 8
    2 2
    1 0
    1 9
    
    b数组输出: 
    1 0
    6 1
    2 2
    7 2
    3 5
    8 5
    4 6
    3 8
    9 8
    1 9
    */ 

    队列&优先队列

    #include<queue>

    啊,这可真是个好东西苍蝇搓手ing

    queue

    queue 模板类的定义在queue头文件中。
    queue 模板类需要两个模板参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为deque 类型。

    queue兹磁的常见操作:

    #include<iostream>
    #include<queue>
    using namespace std;
    int n,x;
    queue <int>q;
    int main()
    {
    cin>>n;
    for(int i=1;i<=n;i++)
    {
    cin>>x;
    q.push(x);//入队,将x接到队列的末端 
    int tail=q.back();//访问队尾元素,即最后被压入队列的元素
    cout<<tail<<" ";
    }
    cout<<endl;
    while(!q.empty())//判断队列空,当队列空时,返回true
    {
    cout<<"size"<<q.size()<<" ";//访问队列中的元素个数
    int TOP=q.front();//访问队首元素
    
    cout<<TOP<<endl;
    q.pop();//出队,弹出队列的第一个元素,并不会返回被弹出元素的值
    }
    return 0;
    }

      

    等价于以下手写代码

    #include<iostream>
    
    using namespace std;
    int n,x;
    int q[10005],head=1,tail=0;
    int main()
    {
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>x;
            q[++tail]=x;
            cout<<q[tail]<<" ";
        }
        cout<<endl;
        while(head<=tail)
        {
            cout<<"size:"<<tail-head+1<<" ";
            cout<<q[head]<<endl;
            head++;
        }
        return 0;
    }
    一组数据:
    输入:
    10
    1 2 3 4 5 6 7 8 9 0
    输出:
    queue:
    1 2 3 4 5 6 7 8 9 0
    size10 1
    size9 2
    size8 3
    size7 4
    size6 5
    size5 6
    size4 7
    size3 8
    size2 9
    size1 0
    手写队:
    1 2 3 4 5 6 7 8 9 0
    size10 1
    size9 2
    size8 3
    size7 4
    size6 5
    size5 6
    size4 7
    size3 8
    size2 9
    size1 0

    priority_queue

    优先队列和队列有神马不同呢?
    优先队列不同于队列,队列是先进先出,优先队列是大数先出(默认)

    #include<iostream>
    #include<queue>
    using namespace std;
    int n,x;
    priority_queue<int>q;
    int main()
    {
        /*
        输入:
        10   
            1 3 5 2 0 4 9 7 8 10 
        */
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>x;
            q.push(x);
            cout<<q.top()<<" "; 
        }
        /*
        输入时队头输出:
         1 3 5 5 5 5 9 9 9 10
        */ 
        cout<<endl;
        while(!q.empty())
        {
            cout<<q.top()<<" ";
            q.pop();    
        }
        /*
        出队顺序:
        10 9 8 7 5 4 3 2 1 0 
        */ 
        return 0;
    }

    如果宁仔细看看就会发现这个B优先队列它其实是个大根堆(默认)
    那我想用优先队列实现dij堆优该咋办呢?
    手写堆 
    重载比较函数
    要小根堆的话,可以
    1.重载operator
    2.c++友情提供的greater<>

    懒得放代码了
    友情赠送一份堆优dij代码

    题目

      1 #include<bits/stdc++.h>
      2 #include<queue>
      3 #define ll long long
      4 #define fo(a,b,c) for(register int a=b;a<=c;a++)
      5 #define fr(a,b,c) for(register int a=b;a>=c;a--)
      6 
      7 using namespace std;
      8 const int N=100005;
      9 const int M=500005;
     10 const int inf=INT_MAX;
     11 int n,m,s;
     12 int vi,ui,wi;
     13 int dis[N];
     14 bool v[N];
     15 inline int read()
     16 {
     17     int x=0,f=1;
     18     char ch=' ';
     19     while(ch<'0'||ch>'9')
     20     {
     21         if(ch=='-')f=-1;
     22         ch=getchar();
     23     }
     24     while(ch>='0'&&ch<='9')
     25     {
     26         x=(x<<3)+(x<<1)+ch-'0';
     27         ch=getchar();
     28     }
     29     return x*f;
     30 }
     31 inline void write(int x)
     32 {
     33     int y=10,len=1;
     34     while(y<=x)
     35     {
     36         y*=10;
     37         len++;
     38     }
     39     while(len--)
     40     {
     41         y/=10;
     42         putchar(x/y+'0');
     43         x%=y;
     44     }
     45 }
     46 int to[M],h[M],w[M],nx[M],cnt=0;
     47 inline void add(int u,int v,int k)
     48 {
     49     to[++cnt]=v;
     50     nx[cnt]=h[u];
     51     h[u]=cnt;
     52     w[cnt]=k;
     53 }
     54 struct node{
     55     int dis,u;
     56     bool operator <(const node& rsh)const{
     57         return rsh.dis<dis;
     58     }
     59 };
     60 priority_queue<node> q;
     61 inline void dij()
     62 {
     63     fo(i,1,n)dis[i]=inf;
     64     dis[s]=0;
     65     q.push((node){0,s});
     66     while(!q.empty())
     67     {
     68         node tmp=q.top();
     69         q.pop();
     70         int x=tmp.u,d=tmp.dis;
     71         if(v[x])continue;
     72         v[x]=1;
     73         for(int i=h[x];i;i=nx[i])
     74         {
     75             int y=to[i];
     76             if(dis[y]>dis[x]+w[i])
     77             {
     78                 dis[y]=dis[x]+w[i];
     79                 if(!v[y])
     80                 {
     81                     q.push((node){dis[y],y});
     82                 }
     83             }
     84         }
     85     }
     86 }
     87 int main()
     88 {
     89     memset(v,0,sizeof(v));
     90     n=read(),m=read(),s=read();
     91     fo(i,1,m)
     92     {
     93         ui=read(),vi=read(),wi=read();
     94         add(ui,vi,wi);
     95         //add(vi,ui,wi);
     96     }
     97     dij();
     98     fo(i,1,n)
     99     {
    100         printf("%d ",dis[i]);
    101         //write(dis[i]);putchar(' ');
    102     }
    103     return 0;
    104 }
    View Code

    二分

    lower_bound()和upper_bound()

    先说说限制条件:
    由于是二分做法,我们需要保证单调性,即必须在有序数组内实现
    关于这俩函数的作用: 如果我们有一个有序序列a(大小为n)和一个x
    lower_bound():找出一个有序数组中第一个大于等于x的值;
    upper_bound():找出一个有序数组中第一个大于x的值;
    dui,这俩货就差个‘=’
    有序数组!,我已经强调了四次了!
    用法:

    lower_bound(a+1,a+1+n,x);
    upper_bound(a+1,a+n+1,x);

    与大多数stl相同,它们也可以重载比较方式

    桥豆麻袋!比较方式??那么问题来了!什么有序序列??

    好了我又要开始强调了qwq
    有序:
    对于比较器有序,且必须是升序
    比较器默认是"<";

    Q:如果要在一个下降序列里寻找一个小于x的数呢?
    cmp cmp cmp!!!

    bool cmp(int a,int b)
    {
        return a>b;
    }

    qwq...
    有没得c++友情提供的greater<>??懒癌晚期实锤
    有!:

    lower_bound(a+1,a+1+n,x,greater<int>());
    upper_bound(a+1,a+1+n,x,greater<int>());

    奥对,这个东东返回的是一个指针
    以lower_bound()为例
    输出a中的第一个大于等于x的值处理

    int p=lower_bound(@#^#$^%)-a;
    cout<<a[p]<<endl;
    ///////////////
    int *p=lower_bound( $#&@%$ !);
    cout<<*p<<endl;

     lower_bound和upper_bound可以优化LIS

    给出一些例题qwq

    导弹拦截

    递增

    改造二叉树

    未完待续....

  • 相关阅读:
    private static final long serialVersionUID = 1L;
    HashMap和Hashtable的区别
    MySQL中tinytext、text、mediumtext和longtext详解
    char、varchar、text和nchar、nvarchar、ntext的区别
    java获取文件夹下文件名
    java删除文件
    js判断浏览器
    nodejs调试:node-inspector
    [转]各种开源协议介绍 BSD、Apache Licence、GPL V2 、GPL V3 、LGPL、MIT
    [IBM]掌握Ajax,Ajax中的高级请求和响应
  • 原文地址:https://www.cnblogs.com/Ln-YJin/p/11647466.html
Copyright © 2011-2022 走看看