1 条题解

  • 0
    @ 2025-8-24 21:56:06

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Iscream2001
    **

    搬运于2025-08-24 21:56:06,当前版本为作者最后更新于2018-11-15 20:37:21,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    提供一个不用自己写数据结构过此题的题解。。。

    合法的区间就是包含所有的在区间内出现过得颜色。。

    这种题有一种神奇的hash做法。。。

    我们给所有颜色相同的位置赋一个值,使得同色的位置的值加起来等于0

    然后统计答案的方法比较显然,维护一个前缀和,然后两个前缀和相同的位置就可以搞出一个合法区间。。

    至于这种做法的正确性。。。感觉记得某大佬曾经证过。。。但是窝不会。。。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<ctime>
    #include<cstdlib>
    #include<vector>
    #include<map>
    #define LL long long
    using namespace std;
    const int N=3e5+10;
    const LL mod=1e12;
    int n;
    int a[N];
    map<LL,LL> mp;
    LL f[N];
    vector<int> ve[N];
    int main(){
        int T;scanf("%d",&T);
        LL re=0,x,op,ans=0;
        while(T--){
            scanf("%d",&n);ans=0;
            for(int i=1;i<=n;++i){
                scanf("%d",&a[i]);
                ve[a[i]].push_back(i);
            }
            for(int i=1;i<=n;++i){
                if(ve[i].size()==0) continue;
                if(ve[i].size()==1) f[ve[i][0]]=0;
                re=0;
                for(int j=0;j<ve[i].size()-1;++j){
                    x=rand()*rand()%mod*rand()%mod*rand()%mod;
                    op=rand()&1;if(op) x=-x;
                    f[ve[i][j]]=x;re+=x;
                }
                f[ve[i][ve[i].size()-1]]=-re;
            }
            mp.clear();re=0;mp[0]=1;
            for(int i=1;i<=n;++i){
                re+=f[i];
                ans+=mp[re];
                ++mp[re];
            }
            printf("%lld\n",ans);
            for(int i=1;i<=n;++i) ve[i].clear();
        }
        return 0;
    }
    
    • 1

    信息

    ID
    3027
    时间
    3000ms
    内存
    500MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者