• Luogu P3823_[NOI2017]蚯蚓排队 哈希+脑子


    之前就写过一遍,今天却写挂了,查了半天发现是数组名写错啦$qwq$


    观察到$K$很小,所以使得我们可以哈希(怎么什么都能哈希$qwq$)。我们把长度小于等于$50$的子串扔到哈希表里,并统计出现次数,注意每次合并和分离时,只加入或删除与断开点距离小于等于$50$的;因为其他子串长度太长,或是已经在前几次中被添加在哈希表里了。

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<cctype>
    #include<cstdlib>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    #define ull unsigned long long
    #define R register int
    using namespace std;
    namespace Fread {
        //static char B[1<<15],*S=B,*D=B;
        //#define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++)
        inline int g() {
            R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
            do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
        }
    }using Fread::g;
    const int N=250000,K=51,mod=998244353,M=19260817,B=11,S=10000010;
    int n,m,q,a[N],pre[N],nxt[N],cnt[N],s[(K<<1)+10];
    ull t[S],p[K<<1];
    namespace HASH {
        struct node { ull vl; int cnt,nxt; node(){}
            node(ull v,int c,int n)    {vl=v,cnt=c,nxt=n;}
        }h[25000010]; int fir[M],cnt=0;
        inline void add(ull x,int d) {
            R st=x%M; for(R i=fir[st];i;i=h[i].nxt) if(h[i].vl==x){
                h[i].cnt+=d; return ;
            } h[++cnt]=node(x,d,fir[st]),fir[st]=cnt;
        }
        inline int query(ull x) {
            R st=x%M; for(R i=fir[st];i;i=h[i].nxt) 
                if(h[i].vl==x) return h[i].cnt; return 0;
        }
        inline void merge() {
            R x=g(),y=g(); memset(s,0,sizeof(s)); R l=K,r=l-1;
            for(R i=x;i&&l>1;i=pre[i]) s[--l]=a[i];
            for(R i=y;i&&r+1<(K<<1);i=nxt[i]) s[++r]=a[i];
            for(R i=1;i<=r;++i) t[i]=t[i-1]*B+s[i];
            for(R i=l;i<K;++i) for(R j=K;j<=r;++j) add(t[j]-t[i-1]*p[j-i+1],1);
            nxt[x]=y,pre[y]=x;
        }
        inline void div() {
            R x=g(),y=nxt[x]; memset(s,0,sizeof(s)); R l=K,r=l-1;
            for(R i=x;i&&l>1;i=pre[i]) s[--l]=a[i];
            for(R i=y;i&&r+1<(K<<1);i=nxt[i]) s[++r]=a[i];
            for(R i=1;i<=r;++i) t[i]=t[i-1]*B+s[i];
            for(R i=l;i<K;++i) for(R j=K;j<=r;++j) add(t[j]-t[i-1]*p[j-i+1],-1);
            nxt[x]=pre[y]=0;
        }
    } 
    char str[11000000];
    inline ll query() { register ull vl=0;
        scanf("%s",str+1); R k=g(),n=strlen(str+1); register ll ans=1;
        if(k==1) for(R i=1;str[i];++i) ans=(ans*cnt[str[i]-'0'])%mod;
        else { for(R i=1;str[i];++i) t[i]=t[i-1]*B+str[i]-'0';
            for(R i=k;str[i];++i) ans=(ans*HASH::query(t[i]-t[i-k]*p[k]))%mod;
        } return ans;
    }
    signed main() {
    #ifdef JACK
        freopen("NOIPAK++.in","r",stdin);
    #endif 
        n=g(),q=g(); p[0]=1; for(R i=1;i<K;++i) p[i]=p[i-1]*B;
        for(R i=1;i<=n;++i) a[i]=g(),++cnt[a[i]];
        while(q--) {
            R k=g(); if(k==1) HASH::merge();
            else if(k==2) HASH::div();
            else printf("%lld
    ",query());
        }
    }
  • 相关阅读:
    构建之法阅读心得(九)
    构建之法阅读心得(八)
    构建之法阅读心得(七)
    构建之法阅读心得(六)
    构建之法阅读心得(五)
    构建之法阅读心得(四)
    一组阶段小记之读构建之法(三)
    暑期学习总结
    软工综合实践 学习笔记02
    软工综合实践 学习笔记01
  • 原文地址:https://www.cnblogs.com/Jackpei/p/11000418.html
Copyright © 2020-2023  润新知