关于multiset的常数问题

前言:

就在这篇博客发布的前几天,【LGR-052】洛谷9月月赛II(加赛)的第二题(链接:https://www.luogu.org/problemnew/show/P4889),这并不是一道很难的题,博主也很快想到了做法并敲出了以下这份代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <set>
typedef long long LL;

inline int read(){
    int x=0;char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x;
}

const int MAXN=200005;
int n,m,a[MAXN];
std::multiset<int> s1,s2;

int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++) a[i]=read();
    LL ans=0;
    for(int i=1;i<=n;i++){
        ans+=s1.count(i-a[i]);
        ans+=s2.count(i+a[i]);
        ans+=s2.count(i-a[i]);
        s1.insert(i-a[i]);
        s2.insert(i+a[i]);
    }
    printf("%lld\n",ans);
    return 0;
}

由于与本文讨论的主题无关,所以在此不阐述本题的详细做法。
不过可以注意到,博主使用了std::multiset (以下简称multiset)储存所有的值,使用了multiset内的.count()函数来统计一个值出现的次数。
众所周知,multiset的.count()函数与set的.count()函数时间复杂度均为O(logn)(n表示集合元素的个数),所以这份代码的时间复杂度为O(nlogn)。
再次众所周知,以O(nlogn)的时间复杂度过n=200,000的数据点本应是很容易,但是博主只得到了30pts,有7个测试点TLE,并且开启O2优化后仍然TLE7个点。
<(OoO)?

后续:

在别人的提醒下,我将multiset换成了map,用一个映射来直接记录一个值出现的次数,敲出了以下代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <map>
typedef long long LL;

inline int read(){
    int x=0;char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x;
}

const int MAXN=200005;
int n,m,a[MAXN];
std::map<int,int> f1,f2;

int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++) a[i]=read();
    LL ans=0;
    for(int i=1;i<=n;i++){
        if(f1.count(i-a[i])) ans+=f1[i-a[i]],f1[i-a[i]]=f1[i-a[i]]+1;
        else f1[i-a[i]]=1;
        if(f2.count(i-a[i])) ans+=f2[i-a[i]];
        if(f2.count(i+a[i])) ans+=f2[i+a[i]],f2[i+a[i]]=f2[i+a[i]]+1;
        else f2[i+a[i]]=1;
    }
    printf("%lld\n",ans);
    return 0;
}

这份代码在不开启O2优化的情况获得了AC。

小结:

在能使用set或map的情况下,尽量避免使用multiset。
例如在这种统计一个数出现了几次这种问题中,multiset的常数我们无法把控,更无法预测它所带来的结果。
一句话,慎用multiset,慎用STL。
(可能还会更新......留个坑。)

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/9698799.html