Re12求调
查看原帖
Re12求调
892222
Sonnety楼主2023/7/20 11:36

调了一上午了,无法解决大面积的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;
}
2023/7/20 11:36
加载中...