【问题标题】:Difference between set.upper_bound() and upper_bound(set.begin(), set.end()) stlset.upper_bound() 和 upper_bound(set.begin(), set.end()) stl 的区别
【发布时间】:2021-02-08 16:08:42
【问题描述】:

https://codeforces.com/contest/1435/submission/96757666 --> 使用 set.upper_bound() https://codeforces.com/contest/1435/submission/96761788 --> 使用了upper_bound(set.begin(), set.end())

我注意到 set.upper_bound() 比后者更快(后者给出了 Time Limit Exceeded)。这是为什么呢?

下面的代码给出了超过时间限制

int ind = *upper_bound(st.begin(), st.end(), mp[i], 更大());

#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
# define ll  long long int
# define ld  long double
# define pb push_back
# define pp pop_back
# define ff first
# define ss second
# define mp make_pair
typedef priority_queue<ll, vector<ll>, greater<ll>> minheap;
typedef priority_queue<ll> maxheap;
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

void solve(){
    int n;
      cin>>n;
      set<int, greater<int>>st;
      st.insert(-1);
      map<int,int> mp;
      int p[2*n];
      char s[2*n];
        for(int i=0;i<2*n;i++)
      {
          cin>>s[i];
          if(s[i]=='+')
          st.insert(i);
          else
          {
              cin>>p[i];
              mp[p[i]]=i;
          }
     
      }
      for(int i=1;i<=n;i++)
      {
        
          int ind = *upper_bound(st.begin(), st.end(), mp[i], greater< int>());
          if(ind==-1||st.find(ind)==st.end())
          {
              // if (-) come before +
              cout<<"NO\n";
              return;
          }
          st.erase(ind);
          p[ind] = i;
          
      }
     
    // cout<<endl;
    stack<int>stc;
    for(int i=0;i<2*n;i++)
    {
        if(s[i]=='+')
        stc.push(p[i]);
        else
        {
            if(stc.top()==p[i])
            stc.pop();
            else
            {
                //if element not in order given in language
                cout<<"NO\n";
                return ;
            }
        }
    }
    cout<<"YES\n";
    for(int i=0;i<2*n;i++)
    {
        if(s[i]=='+')
        cout<<p[i]<<endl;
    }
    return;
}   


int  main()
{
    #ifndef ONLINE_JUDGE
       freopen("input.txt", "r", stdin);
       freopen("output.txt", "w", stdout);
    #endif
      IOS
     int t = 1;
     //cin >> t;
     while(t--){
        solve();
     }
    return 0;
}

与“set.upper_bound()”相同的代码在时间限制内执行。

int ind = *st.upper_bound(mp[i]);

#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
# define ll  long long int
# define ld  long double
# define pb push_back
# define pp pop_back
# define ff first
# define ss second
# define mp make_pair
typedef priority_queue<ll, vector<ll>, greater<ll>> minheap;
typedef priority_queue<ll> maxheap;
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

void solve(){
    int n;
      cin>>n;
      set<int, greater<int>>st;
      st.insert(-1);
      map<int,int> mp;
      int p[2*n];
      char s[2*n];
        for(int i=0;i<2*n;i++)
      {
          cin>>s[i];
          if(s[i]=='+')
          st.insert(i);
          else
          {
              cin>>p[i];
              mp[p[i]]=i;
          }
     
      }
      for(int i=1;i<=n;i++)
      {
        
          int ind = *st.upper_bound(mp[i]);
          if(ind==-1||st.find(ind)==st.end())
          {
              // if (-) come before +
              cout<<"NO\n";
              return;
          }
          st.erase(ind);
          p[ind] = i;
          
      }
     
    // cout<<endl;
    stack<int>stc;
    for(int i=0;i<2*n;i++)
    {
        if(s[i]=='+')
        stc.push(p[i]);
        else
        {
            if(stc.top()==p[i])
            stc.pop();
            else
            {
                //if element not in order given in language
                cout<<"NO\n";
                return ;
            }
        }
    }
    cout<<"YES\n";
    for(int i=0;i<2*n;i++)
    {
        if(s[i]=='+')
        cout<<p[i]<<endl;
    }
    return;
}   


int  main()
{
    #ifndef ONLINE_JUDGE
       freopen("input.txt", "r", stdin);
       freopen("output.txt", "w", stdout);
    #endif
      IOS
     int t = 1;
     //cin >> t;
     while(t--){
        solve();
     }
    return 0;
}

【问题讨论】:

  • 请将您的代码直接添加到 StackOverflow。链接到外部站点并在将来中断。将其作为文本放在此处还可以让搜索引擎将您的问题编入索引,以供其他人将来查找。
  • 代码很大,我应该只添加相关部分还是整个代码?
  • @BerubolV 是的,请。
  • @J'e 整个代码?
  • @TedLyngmo 谢谢,我现在就去做。

标签: c++ stl


【解决方案1】:

set::upper_bound 将使用集合的功能来有效地搜索 value(与容器大小相关的对数)。

对于std::upper_bound,使用非LegacyRandomAccessIterators,如std::sets 迭代器(即LegacyBidirectionalIterators),迭代器增量的数量是线性的。

【讨论】:

  • 那么我们应该总是使用“LegacyRandomAccessIterators”吗?因为在大多数网站上人们使用 upper_bound(set.begin(), set.end())。
  • @BeruboIV 不,如果你有std::set,你应该使用std::set::upper_bound 而不是std::upper_bound(因为std::set 没有LegacyRandomAccessIterators)。另一方面,如果您有std::vector,那么std::upper_bound 将是有效的。
  • @BeruboIV 一些容器可以比通用算法更有效地执行某些操作。 std::map::findstd::find 是另一个例子。当一个容器有一个foo 作为成员时,通常这比std::foo 通用的更受欢迎
  • @BeruboIV 我制作了一个upper_bound 函数模板,它根据您使用的容器使用正确的upper_bound 函数。也许它可以使用:upper_bound
  • @BeruboIV 不,这在无法排序的容器上是不可能的,但如果容器有成员函数upper_bound,它将选择成员函数(map、@987654345 是这样) @、multimapmultiset、他们的pmr 版本和任何用户定义的容器),其余使用std::upper_bound。对于像 vector 这样的容器,它会进行二分搜索,但对于像 list 这样的容器,它不会(因为 list 没有 LegacyRandomAccessIterators 并且进行二分搜索会比只是循环直到找到上限)。
猜你喜欢
  • 1970-01-01
  • 2012-05-20
  • 1970-01-01
  • 2020-08-09
  • 1970-01-01
  • 1970-01-01
  • 2010-09-21
  • 2011-01-31
  • 1970-01-01
相关资源
最近更新 更多