调了一上午了,无法解决大面积的Re问题,数组再开大一些就不能编译了,O2开不开都是Re
#include<bits/stdc++.h>
using namespace std;
inline int read(){
char c=getchar();
int x=0,f=1;
while(c<48){if(c=='-')f=-1;c=getchar();}
while(c>47)x=(x*10)+(c^48),c=getchar();
return x*f;
}
typedef long long intx;
const int maxn=2e5+50,maxm=5e5+50,maxk=100,maxs=1e7+50;
const int mod=998244353;
const intx p=17,mm=19491001;
int n,m,ewl[maxn];
intx pp[maxk],p10[maxk],vcnt[maxk];
char ns[maxs],nlen;
int to[maxn],tp[maxn]; //to[i],tp[i]分别表示i的后一个和前一个
int t=0,head[mm+50];
struct edge{
int next_,cnt;
intx w;
};edge e[mm+50];
inline void input(){
n=read();m=read();
for(int i=1;i<=n;++i){
ewl[i]=read();
++vcnt[ewl[i]];
}
pp[0]=1,p10[0]=1;
for(int i=1;i<=50;++i){
pp[i]=pp[i-1]*p%mm;
p10[i]=p10[i-1]*10;
}
}
void add(intx hash,intx q){
//哈希表,如果对于hash这个值有q这个原值则++cnt,否则新开一点
for(int i=head[hash];i;i=e[i].next_){
if(e[i].w==q){
++e[i].cnt;
return;
}
}
e[++t].cnt=1;
e[t].w=q;
e[t].next_=head[hash];
head[hash]=t;
}
void delet(intx hash,intx q){
//删边肯定有这个边啊,--cnt就可以了
for(int i=head[hash];i;i=e[i].next_){
if(e[i].w==q){
--e[i].cnt;
return;
}
}
}
int query(intx hash,intx q){
for(int i=head[hash];i;i=e[i].next_){
if(e[i].w==q){
return e[i].cnt;
}
}
return 0;
}
int s1[maxk],s2[maxk]; //s1是x之前的数字串,s2是y之后的数字串
inline void merge(int x,int y){
//把x之前的hash取出来,在后面加上y的hash
int l1=0,l2=0;
intx hsh=0,q=0,hxh=0,qx=0;
to[x]=y;
tp[y]=x;
for(int i=x;i && l1<49;i=tp[i]){
s1[++l1]=ewl[i];
hsh=(hsh+ewl[i]*pp[l1-1])%mm;
q=q+ewl[i]*p10[l1-1];
//将x与x之前的串(最长50)倒序取出,s1是倒叙的,hsh是正序的
}
for(int i=y;i && l2<49; i=to[i]) s2[++l2]=ewl[i];
//将y与y之后的串(最长50)正序取出
for(int i=l1;i>=1;--i){
//倒序取出的串倒叙枚举
hxh=0,qx=0;
for(int j=1;j<=l2 && i+j<=50;++j){
hxh=(hxh*p+s2[j])%mm;
qx=qx*10+s2[j];
//cout<<"$$$"<<(hsh*pp[j]%mm+hxh)%mm<<' '<<q*p10[j]+qx<<endl;
add((hsh*pp[j]%mm+hxh)%mm,q*p10[j]+qx);
}
hsh=(hsh-pp[i-1]*s1[i]%mm+mm)%mm;
q=q-p10[i-1]*s1[i];
}
}
inline void separate(int x,int y){
//同merge
int l1=0,l2=0;
intx hsh=0,q=0,hxh=0,qx=0;
to[x]=0;
tp[y]=0;
for(int i=x;i && l1<49;i=tp[i]){
s1[++l1]=ewl[i];
hsh=(hsh+ewl[i]*pp[l1-1])%mm;
q=q+ewl[i]*p10[l1-1];
}
for(int i=y;i && l2<49;i=to[i]){
s2[++l2]=ewl[i];
}
for(int i=l1;i>=1;--i){
hxh=0,qx=0;
for(int j=1;j<=l2 && i+j<+50;++j){
hxh=(hxh*p+s2[j])%mm;
qx=qx*10+s2[j];
delet((hsh*pp[j]%mm+hxh)%mm,q*p10[j]+qx);
}
hsh=(hsh-pp[i-1]*s1[i]%mm+mm)%mm;
q=q-p10[i-1]*s1[i];
}
}
inline void work3(int x){
intx hsh=0,q=0,ans=1;
if(x==1){
//询问长度为1的串,在读入的时候我们开了一个桶vcnt统计答案
for(int i=1;i<=nlen;++i) ans=ans*vcnt[ns[i]-'0']%mod;
printf("%lld\n",ans%mod);
return;
}
for(int i=1;i<=x;++i){
hsh=(hsh*p+ns[i]-'0')%mod;
q=q*10+ns[i]-'0';
}
//cout<<"###"<<hsh<<endl;
ans=query(hsh,q)%mod;
for(int i=x+1;i<=nlen;++i){
hsh=(((hsh-(ns[i-x]-'0')*pp[x-1])%mm+mm)%mm*p+ns[i]-'0')%mm;
//求长度为x的字符串的哈希值
q=(q-(ns[i-x]-'0')*p10[x-1])*10+ns[i]-'0';
//cout<<"###"<<hsh<<' '<<q<<' '<<query(hsh,q)<<endl;
ans=ans*query(hsh,q)%mod;
}
printf("%lld\n",ans);
}
int main(){
freopen("P3823_2.in","r",stdin);
freopen("myout.txt","w",stdout);
input();
int opt,x,y;
while(m--){
opt=read();
if(opt==1){
x=read();
y=read();
merge(x,y);
}
else if(opt==2){
x=read();
separate(x,to[x]);
}
else{
scanf("%s",ns+1);
nlen=strlen(ns+1);
x=read();
work3(x);
}
}
return 0;
}