• stl测试


    以下测试都在学校电脑进行 我觉得应该比考试机器慢一点。。

    1.map

    map的速度测出来和放入数值大小有很大关系

    比如 

    #include <bits/stdc++.h>
    using namespace std;
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    const int N=1e6;
    const int mo=100;
    map<int,int> M;
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      rep(i,1,N)
      {
        int x=rand()%mo;
        M[x]++;
      }
      int ans=0;
      rep(i,1,N)
      {
        int x=rand()%mo+1,y=rand()%mo+1;
        ans+=M[x]-M[y];
      }
      cout<<ans<<endl;
      return 0;
    }

    在mo=100的时候开O2仅0.4s 不开O2 1.2s

    而在mo=1e9的情况下开O2跑了7s 不开O2跑了12s

    于是我尝试了一下hash 开不开O2都差不多0.7s

    #include <bits/stdc++.h>
    using namespace std;
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    const int N=1e6;
    const int mo=1000000000;
    map<int,int> M;
    const int hashmo=1e7+7;
    struct re{
      int a,b;
    }ha[hashmo+100000];
    struct hash{
      void insert(int x)
      {
        int y=x%hashmo;
        while (ha[y].a&&ha[y].a!=x) y++;
        ha[y].a=x; ha[y].b++;
      }
      int find(int x)
      {
        int y=x%hashmo;
        while (ha[y].a&&ha[y].a!=x) y++;
        return ha[y].b;
      }
    }H;
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      rep(i,1,N)
      {
        int x=rand()%mo;
        H.insert(x);
      }
      int ans=0;
      rep(i,1,N)
      {
        int x=rand()%mo+1,y=rand()%mo+1;
        ans+=H.find(x)-H.find(y);
      }
      cout<<ans<<endl;
      return 0;
    }

    gprof了一下

    % cumulative self self total
    time seconds seconds calls ns/call ns/call name

    50.00 0.27 0.27 2000000 135.00 135.00 hash::find(int)
    42.59 0.50 0.23 1000000 230.00 230.00 hash::insert(int)

    所以不到没有时间或者题目时间对这个很宽松的时候(或者这个比较难写hash)

    尽量使用手写hash

    hash在5e6的时候

    不开O2 3.7s 开O2 3.7s

    所以考试的上限大概就这么多了

    当然hash在模数较小的情况下表现也会更好

    2.set

    首先set的操作比较多,先说一下

    insert嘛人人都知道

    find注意只能查找这个元素,如果没有就会指向end(空)

    lower_bound 查找.>=x的最小元素 upper_bound 查找>x的最小元素

    erase(x) 删去所有等于x的元素 注意如果你用multiset然后想只删一个 那么可以it=S.find() S.earse(it)

    count(x) 查找=x的元素个数(这个操作并没有啥用因为可以用map)

    但是有的时候我们需要重载运算符

    如下

    #include <bits/stdc++.h>
    using namespace std;
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    #define dep(i,t,h) for (int i=t;i>=h;i--)
    struct cmp{
      bool operator () (int x,int y)
      {
        return x>y;
      }
    };
    set<int,cmp> S;
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      
      
      return 0;
    }

    这样就定义了从大到小的set

    但这种情况下假如要用lower_bound怎么办呢

    我们测试一下

    #include <bits/stdc++.h>
    using namespace std;
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    #define dep(i,t,h) for (int i=t;i>=h;i--)
    struct cmp{
      bool operator () (int x,int y)
      {
        return x>y;
      }
    };
    set<int,cmp> S;
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      S.insert(1); S.insert(2); S.insert(3); S.insert(4);
      cout<<*S.upper_bound(4)<<" "<<*S.lower_bound(4)<<endl;
      return 0;
    }

    输出的是3,4

    其实我们可以这么去看,现在元素是从大到小排序

    我们upper_bound 是查找这个数右边(不包括自己) 而lower_bound是查找这个数右边包括自己的

    于是这样我们就可以在cmp后继续使用lower/upper _bound查找了

    但是现在还有一个问题,如果我想查找<=x的最大数呢

    方案1:修改cmp

    方案2:S.upper_bound()-- (当然要特判断一下不存在)

    如果查找<x的最大数呢

    方案2:S.lower_bound()--(同理也得特判)

    另一个问题是set的遍历

    有的时候我们写启发式合并然后时间比较宽松就会用set来替代

    (平衡树毕竟个人感觉是最难调的数据结构)

    for (it=S.begin();it!=S.end();it++) 这样遍历

    有的时候我们需要求it的后继但并不像改变it的值,可以这么写

    #define setit set<int>::iterator

    setit scc(setit it )

    {

      setit it2=it; it2++; return it2;

    }

    这就是it的基本操作了

    接下来开始测速度

    #include <bits/stdc++.h>
    using namespace std;
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    #define dep(i,t,h) for (int i=t;i>=h;i--)
    #define ll long long
    struct cmp{
      IL bool operator () (int x,int y)
      {
        return x>y;
      }
    };
    set<int,cmp> S;
    set<int,cmp>::iterator it;
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      int n=1e6;
      rep(i,1,n) S.insert(rand());
      ll ans=0;
      for (it=S.begin();it!=S.end();it++)
      {
        ans+=*it;
      }
      cout<<ans<<endl;
      return 0;
    }

    不开O2 3s 开O2 2s 

    #include <bits/stdc++.h>
    using namespace std;
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    #define dep(i,t,h) for (int i=t;i>=h;i--)
    #define ll long long
    struct cmp{
      IL bool operator () (int x,int y)
      {
        return x>y;
      }
    };
    set<int,cmp> S;
    set<int,cmp>::iterator it;
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      int n=1e6;
      rep(i,1,n) S.insert(rand()%100);
      ll ans=0;
      for (it=S.begin();it!=S.end();it++)
      {
        ans+=*it;
      }
      cout<<ans<<endl;
      return 0;
    }

    不开O2 0.5s 开O2 0.3s

    这个代码和刚才一样

    当数值都较小时就快很多

    我不是很清楚原理

    不过这也告诉了我们离散化在卡常上挺重要的

    #include <bits/stdc++.h>
    using namespace std;
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    #define dep(i,t,h) for (int i=t;i>=h;i--)
    #define ll long long
    struct cmp{
      IL bool operator () (int x,int y)
      {
        return x>y;
      }
    };
    set<int,cmp> S;
    set<int,cmp>::iterator it;
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      int n=1e6;
      rep(i,1,n) S.insert(rand());
      ll ans=0;
      rep(i,1,n) ans+=*S.find(rand());
      cout<<ans<<endl;
      return 0;
    }

    不开O2 4.6s 开O2 3.6s

    同理把find变成upper_bound时间几乎差不多

    所以考试的时候 当数据范围不是很大的时候 1e6次插入基本可以接受

    3.vector

    #include <bits/stdc++.h>
    using namespace std;
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    #define dep(i,t,h) for (int i=t;i>=h;i--)
    #define ll long long
    vector<int> ve;
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      int n=1e7;
      rep(i,1,n) ve.push_back(rand());
      ll ans=0;
      rep(i,1,n) ans+=ve[i-1];
      cout<<ans<<endl;
      return 0;
    }

    不开O2 0.85s 开O2 0.75s

    #include <bits/stdc++.h>
    using namespace std;
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    #define dep(i,t,h) for (int i=t;i>=h;i--)
    #define ll long long
    const int N=2e7;
    int ve[N];
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      int n=1e7;
      rep(i,1,n) ve[i]=rand();
      ll ans=0;
      rep(i,1,n) ans+=ve[i-1];
      cout<<ans<<endl;
      return 0;
    }

    而数组 不开O2 0.55s 开O2 0.4s

    这说明了的确会慢一点

    再大的数组一般用不到 大的数组访问还是挺慢的

    4.queue

    #include <bits/stdc++.h>
    using namespace std;
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    #define dep(i,t,h) for (int i=t;i>=h;i--)
    #define ll long long
    queue<int> q;
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      int n=1e7;
      rep(i,1,n) q.push(rand());
      ll ans=0;
      rep(i,1,n) ans+=q.front();
      cout<<ans<<endl;
      return 0;
    } 

    不开O2 2s 的确是非常的慢

    不过开O2 0.6s???? 这个还可以

    所以在一些线性算法时间比较仅的情况下 尽量使用数组

    5.deque

    这个东西让我很震惊

    #include <bits/stdc++.h>
    using namespace std;
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    #define dep(i,t,h) for (int i=t;i>=h;i--)
    #define ll long long
    deque<int> q;
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      int n=1e7;
      rep(i,1,n) q.push_front(rand());
      ll ans=0;
      rep(i,1,n) ans+=q.front();
      cout<<ans<<endl;
      return 0;
    }

    不开O2 1s 开O2 0.5s

    比queue快是什么操作啊。。

    这个东西简直是个神仙东西。。

    还有各种操作。。(在雅礼里面写了 下次再补)

    6.priority_queue

    这个东西强O2需要求啊。。

    #include <bits/stdc++.h>
    using namespace std;
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    #define dep(i,t,h) for (int i=t;i>=h;i--)
    #define ll long long
    priority_queue<int> q;
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      int n=1e6;
      rep(i,1,n) q.push(rand());
      ll ans=0;
      rep(i,1,n) ans+=q.top(),q.pop();
      return 0;
    }

    不开O2 3s 开O2 0.6s

    也就是说不开O2下和set速度差不多 开O2吊打set

    像去年d1t3 最坏情况下5e6次priority操作 所以开始写就要意识常数问题了

    最短路一般没什么优化余地 我去网上看了一下线段树和堆优化

    几乎跑的差不多

  • 相关阅读:
    遗传学详解及Matlab算法实现
    (转)非常好的理解遗传算法的例子
    Halcon学习笔记之支持向量机(二)
    Hough 变换
    主元分析PCA理论分析及应用
    Retinex图像增强算法
    Halcon学习笔记之支持向量机(一)
    阿里云OSS安装使用问题
    JS中双击和单击事件冲突解决
    JavaScript正则表达式应用---replace()
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9915598.html
Copyright © 2020-2023  润新知