D题分块,赛时卡MLE,求助
  • 板块学术版
  • 楼主piggy123
  • 当前回复4
  • 已保存回复4
  • 发布时间2022/10/5 12:34
  • 上次更新2023/10/27 08:43:29
查看原帖
D题分块,赛时卡MLE,求助
380042
piggy123楼主2022/10/5 12:34
#include <bits/stdc++.h>
#define ll int
#define ull unsigned long long
using namespace std;

ll fac[10000005],a[100005],ff[40005],sm[40005],n,q,mod=998244353;
int sq[405][100005],rt[405][100005],fa[100005],blo;
ll qkp(ll a,ll k) {
	ll ans=1;
	while (k) {
		if (k&1)ans=1ll*ans*a%mod;
		a=1ll*a*a%mod;
		k>>=1;
	}
	return ans;
}

inline ll find(ll a){
	if (fa[a]!=a)fa[a]=find(fa[a]);
	return fa[a];
}

void brute(ll x){
	for (ll i=(x-1)*blo+1;i<=min(n,x*blo);i++){
		rt[x][a[i]]=0;
		fa[i]=i;
	}
	for (ll i=(x-1)*blo+1;i<=min(n,x*blo);i++){
		if (!rt[x][a[i]])rt[x][a[i]]=i;
		else fa[i]=rt[x][a[i]];
	}
}

int main() {
	fac[0]=1;
	for (ll i=1; i<=10000000; i++){
		fac[i]=1ll*fac[i-1]*i%mod;
	}
//	cin >> n >> q;
	scanf("%d%d",&n,&q);
	blo=sqrt(n);
	for (ll i=1; i<=n; i++) {
//		cin >> a[i];
		scanf("%d",a+i);
		ff[(i-1)/blo+1]=1;
	}
	for (ll i=1; i<=n; i++) {
		fa[i]=i;
		ll bel=(i-1)/blo+1;
		sq[bel][a[i]]++;
		ff[bel]=1ll*ff[bel]*fac[a[i]]%mod;
		sm[bel]+=a[i];
	}
	for (ll i=1;i<=(n-1)/blo+1;i++){
		for (ll j=(i-1)*blo+1;j<=min(n,i*blo);j++){
			if (!rt[i][a[j]])rt[i][a[j]]=j;
			else fa[j]=rt[i][a[j]];
		}
	}
	for (ll z=1; z<=q; z++) {
		ll op,l,r,x,y;
//		cin >> op;
		scanf("%d",&op);
		if (op==1) {
//			cin >> l>> r>>x >> y;
			scanf("%d%d%d%d",&l,&r,&x,&y);
			if (x==y)continue;
			ll posl=(l-1)/blo+1,posr=(r-1)/blo+1;
			if (posl==posr) {
				for (ll i=l; i<=r; i++) {
					a[i]=a[find(i)];
					if (a[i]==x){
						a[i]=y;
						sq[posl][x]--;
						sq[posl][y]++;
						ff[posl]=1ll*ff[posl]*qkp(fac[x],mod-2)%mod*fac[y]%mod;
						sm[posl]-=x;
						sm[posl]+=y;
					}
				}
				brute(posl);
			} else {
				for (ll i=(posl-1)*blo+1;i<=posl*blo;i++)a[i]=a[find(i)];
				for (ll i=(posr-1)*blo+1;i<=min(n,posr*blo);i++)a[i]=a[find(i)];
				for (ll i=l; i<=posl*blo; i++) {
					if (a[i]==x){
						a[i]=y;
						sq[posl][x]--;
						sq[posl][y]++;
						ff[posl]=1ll*ff[posl]*qkp(fac[x],mod-2)%mod*fac[y]%mod;
						sm[posl]-=x;
						sm[posl]+=y;
					}
				}
				for (ll i=posl+1;i<posr;i++){
					if (sq[i][x]){
						if(!rt[i][y])rt[i][y]=rt[i][x],a[rt[i][x]]=y;
						else fa[rt[i][x]]=rt[i][y];
						ll p=sq[i][x];
						sq[i][y]+=p;
						sq[i][x]-=p;
						ff[i]=1ll*ff[i]*qkp(qkp(fac[x],p),mod-2)%mod*qkp(fac[y],p)%mod;
						sm[i]-=x*p;
						sm[i]+=y*p;
					}
				}
				for (ll i=(posr-1)*blo+1; i<=r; i++) {
					if (a[i]==x){
						a[i]=y;
						sq[posr][x]--;
						sq[posr][y]++;
						ff[posr]=1ll*ff[posr]*qkp(fac[x],mod-2)%mod*fac[y]%mod;
						sm[posr]-=x;
						sm[posr]+=y;
					}
				}
				brute(posl);
				brute(posr);
			}
		} else {
			// 区间和 区间阶乘和
//			cin >>l>>r;
			scanf("%d%d",&l,&r);
			ll ss=0,sm2=1;
			ll posl=(l-1)/blo+1,posr=(r-1)/blo+1;
			if (posl==posr) {
				for (ll i=l; i<=r; i++) {
					a[i]=a[find(i)];
					ss+=a[i];
					sm2=1ll*sm2*fac[a[i]]%mod;
				}
			} else {
				for (ll i=l; i<=posl*blo; i++) {
					a[i]=a[find(i)];
					ss+=a[i];
					sm2=1ll*sm2*fac[a[i]]%mod;
				}
				for (ll i=posl+1;i<posr;i++){
					ss+=sm[i];
					sm2=1ll*sm2*ff[i]%mod;
				}
				for (ll i=(posr-1)*blo+1; i<=r; i++) {
					a[i]=a[find(i)];
					ss+=a[i];
					sm2=1ll*sm2*fac[a[i]]%mod;
				}
			}
			printf("%lld\n",1ll*fac[ss]*qkp(sm2,mod-2)%mod);
//			cout << << endl;
		}
	}
	return 0;
}
2022/10/5 12:34
加载中...