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\n",query());
    }
}

 

posted @ 2019-06-10 21:32  LuitaryiJack  阅读(181)  评论(0编辑  收藏  举报