• 「ZJOI2022」众数


    d1t2

    大家好,我不会根号实锤了。

    因为跟众数有关并且看起来就要对所有种类的数求一个答案,可以直接考虑根号算法。

    没有什么好的分块思路,不妨根号分治。按数的种类处理,按大小分治:

    • 出现次数大于 \(\sqrt n\):这种数最多 \(O(\sqrt n)\) 个,颜色是 \(O(n)\) 个的,每种颜色处理一下就是 \(O(n \sqrt n)\) 的;
    • 出现次数小于等于 \(\sqrt n\):记其出现位置为 \(p_0=0,p_1,p_2,\cdots ,p_k,p_{k+1}=n+1\),那么改 \((p_i, p_j)\) 对这种数来说最优,枚举 \(i,j\),总时间复杂度分析后可知是 \(O(n \sqrt n)\) 的。

    然后先处理出现次数大于 \(\sqrt n\) 的。假设这种颜色为 \(p\),我们试图把 \(p\) 改成 \(q\) 更新 \(q\),或是把 \(q\) 改成 \(p\) 更新 \(p\)。维护 \(p\) 出现次数的前缀和直接处理,这是简单的。

    然后再处理出现次数不大于 \(\sqrt n\) 的数。注意到一点是在上面的处理中我们处理了一个出现次数大于 \(\sqrt n\) 的数 \(p\) 改成出现次数不大于 \(\sqrt n\) 的数 \(q\),所以在这里只考虑两个数出现次数都不大于 \(\sqrt n\) 的。

    那么相当于做 \(O(n \sqrt n)\) 次区间众数。但是有一点是每个数出现次数都是不大于 \(O(\sqrt n)\) 的。那么记 \(s_i\)\([i,n]\) 的众数出现次数,容易发现 \(\sum s_i = O(n \sqrt n)\) 的,其支持暴力维护。

    暴力枚举 \([l,r]\)。现在已经枚举了 \(r\),再枚举 \(l\)。容易发现我们可以根据上面分讨得出的一个简单小结论优化枚举过程,也就是保证 \(l-1\)\(r\) 颜色一样,或者 \(l=1\) 即可。显然 \(s_i \geq s_{i-1}\),我们可以暴力更新 \([i,r]\) 的区间众数,更新次数不大于 \(O(n \sqrt n)\),可以保证复杂度。

    代码比题解清楚。

    void SmChunk()
    {
        for(int i=1;i<=n;++i)   sum[i]=0;
        for(int i=1;i<=n;++i)
        {
            if(app[a[i]]<=Sqr)
            {
                int p=lower_bound(Pos[a[i]].begin(),Pos[a[i]].end(),i)-Pos[a[i]].begin();
                for(int j=p;~j;--j)
                {
                    int l=j?Pos[a[i]][j-1]+1:1,r=Pos[a[i]][j];
                    maxn[a[i]]=max(maxn[a[i]],sum[l]-(p-j));
                    while(l<=r && sum[r]<p-j+1) sum[r--]=p-j+1;
                }
            }
        }
    }
    void Solve()
    {
        n=read();
        for(int i=1;i<=n;++i)   a[i]=b[i]=read();
        sort(b+1,b+1+n);
        len=unique(b+1,b+1+n)-b-1;
        for(int i=1;i<=n;++i)   a[i]=lower_bound(b+1,b+1+len,a[i])-b;
        for(int i=1;i<=len;++i) app[i]=0,Pos[i].clear(),maxn[i]=0;
        for(int i=1;i<=n;++i)   ++app[a[i]],Pos[a[i]].push_back(i);
        for(int p=1;p<=len;++p)
        {
            if(app[p]>Sqr)
            {
                for(int i=1;i<=n;++i)   sum[i]=sum[i-1]+int(a[i]==p);
                for(int q=1;q<=len;++q)
                {
                    int N=app[q],l,s;
                    l=s=0;
                    for(int i=0;i<N;++i)
                    {
                        int r=Pos[q][i];
                        s=max(0,s-(sum[r]-sum[l]))+1;
                        maxn[p]=max(maxn[p],s);
                        l=r;
                    }
                    l=s=0;
                    for(int i=0;i<N;++i)
                    {
                        int r=Pos[q][i];
                        s=max(0,s)+sum[r]-sum[l];
                        maxn[q]=max(maxn[q],s--);
                        l=r;
                    }
                }
            }
        }
        SmChunk();
        reverse(a+1,a+1+n);
        for(int i=1;i<=len;++i)
        {
            reverse(Pos[i].begin(),Pos[i].end());
            for(auto &st:Pos[i])    st=n-st+1;
        }
        SmChunk();
        for(int i=1;i<=len;++i) maxn[i]+=app[i];
        int ans=0;
        for(int i=1;i<=len;++i) ans=max(ans,maxn[i]);
        write(ans),puts("");
        for(int i=1;i<=len;++i) if(maxn[i]==ans)    write(b[i]),puts("");
    }
    
  • 相关阅读:
    20180929 北京大学 人工智能实践:Tensorflow笔记02
    20180929 北京大学 人工智能实践:Tensorflow笔记01
    YOLOv3学习笔记
    编辑器上传漏洞
    IIS解析漏洞利用
    数据库备份及审查元素进行webshell上传
    burp suite 进行webshell上传
    BUGKU CFT初学之WEB
    CTFbugku--菜鸟初学
    理解PHP中的会话控制
  • 原文地址:https://www.cnblogs.com/amagaisite/p/16283500.html
Copyright © 2020-2023  润新知