• 「NOI2017」蚯蚓排队 解题报告


    「NOI2017」蚯蚓排队

    这题真的草

    你考虑(k)这么小,每次合并两个串,增加的有用串的数量是(O(k^2))的,暴力加入这些串,求一下这些串的Hash值,塞到Hash表里面去

    这里采用类似双hash的方法,一个表进行拉表,另一个表存这个串的权值

    然后就是暴力搞了

    犯了个很sb的错误,我把每个蚯蚓长度都-1了,这样很容易爆Hash

    不过我最开始是对每个长度的串开一个Hash数组搞,这样空间大,时间常数大,卡不过去,但不会因为长度为0的情况爆hash

    最后回来的时候,一直爆Hash到自闭了...


    Code:

    //#pragma GCC optimize("Ofast")
    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <algorithm>
    #define ll long long
    #define ull unsigned long long
    using std::min;
    const int SIZE=1<<21;
    char ibuf[SIZE],*iS,*iT;
    #define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),iS==iT?EOF:*iS++):*iS++)
    //#define gc() getchar()
    template <class T>
    void read(T &x)
    {
        int f=0;x=0;char c=gc();
        while(!isdigit(c)) f|=c=='-',c=gc();
        while(isdigit(c)) x=x*10+c-'0',c=gc();
        if(f) x=-x;
    }
    void reads(int *s)
    {
        char c=gc();
        while(!isdigit(c)) c=gc();
        while(isdigit(c)) s[++s[0]]=c-'0',c=gc();
    }
    const int N=300010;
    const int mod=19491001;
    struct Hash
    {
        int head[mod],Next[N*50],siz[N*50],cnt;
        ull idx[N*50];
        void ins(int x,ull id)
        {
            for(int i=head[x];i;i=Next[i])
                if(id==idx[i])
                {
                    ++siz[i];
                    return;
                }
            Next[++cnt]=head[x],head[x]=cnt;
            siz[cnt]=1;
            idx[cnt]=id;
        }
        void era(int x,ull id)
        {
            for(int i=head[x];i;i=Next[i])
                if(id==idx[i])
                {
                    --siz[i];
                    return;
                }
            puts("err");
        }
        int qry(int x,ull id)
        {
            for(int i=head[x];i;i=Next[i])
                if(id==idx[i])
                    return siz[i];
            return 0;
        }
    }Ha;
    const int bas=13131;
    const int bas2=131;
    int n,m,pre[N],suc[N],num[N],s[N];
    int saki[233];
    int main()
    {
        read(n),read(m);
        for(int i=1;i<=n;i++)
        {
            ull idx;
            read(num[i]);
            idx=num[i];
            Ha.ins(num[i],idx);
        }
        for(int op,u,v,k,i=1;i<=m;i++)
        {
            read(op);
            if(op==1)
            {
                read(u),read(v);
                suc[u]=v,pre[v]=u;
                int now=u,l=51,r=50;
                while(now&&l)
                {
                    saki[--l]=num[now];
                    now=pre[now];
                }
                now=v;
                while(now&&r<=100)
                {
                    saki[++r]=num[now];
                    now=suc[now];
                }
                for(int i=l;i<=50;i++)
                {
                    ull idx=0;
                    int x=0;
                    for(int j=i;j<=i+49&&j<=r;j++)
                    {
                        x=(1ll*x*bas+saki[j])%mod;
                        idx=idx*bas2+saki[j];
                        if(j>50) Ha.ins(x,idx);
                    }
                }
            }
            else if(op==2)
            {
                read(u),v=suc[u];
                int now=u,l=51,r=50;
                while(now&&l)
                {
                    saki[--l]=num[now];
                    now=pre[now];
                }
                now=v;
                while(now&&r<=100)
                {
                    saki[++r]=num[now];
                    now=suc[now];
                }
                for(int i=l;i<=50;i++)
                {
                    ull idx=0;
                    int x=0;
                    for(int j=i;j<=i+49&&j<=r;j++)
                    {
                        x=(1ll*x*bas+saki[j])%mod;
                        idx=idx*bas2+saki[j];
                        if(j>50) Ha.era(x,idx);
                    }
                }
                suc[u]=pre[v]=0;
            }
            else
            {
                int ans=1;
                s[0]=0;
                reads(s),read(k);
                int po=1,x=0;ull ba=1,idx=0;
                for(int i=1;i<k;i++) po=1ll*po*bas%mod,ba=ba*bas2;
                for(int i=1;i<k;i++) idx=idx*bas2+s[i],x=(1ll*x*bas+s[i])%mod;
                for(int i=k;i<=s[0];i++)
                {
                    idx=idx*bas2+s[i],x=(1ll*x*bas+s[i])%mod;
                    ans=1ll*ans*Ha.qry(x,idx)%998244353;
                    if(!ans) break;
                    idx-=s[i-k+1]*ba;
                    x-=1ll*s[i-k+1]*po%mod;
                    if(x<0) x+=mod;
                }
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    
    

    2019.6.1

  • 相关阅读:
    mysql qps tps
    SQL RIGHT JOIN 关键字
    C#的多态性
    c# 与java之间的简单区别
    多少行转多少列
    SQL语句中&、单引号等特殊符号的处理
    sql 函数的理解
    c# 基础之数组(包含三维数组)
    泛型之Dictionary
    在十六进制字符串与数值类型之间转换
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10959076.html
Copyright © 2020-2023  润新知