蒟蒻刚学分块,求调
查看原帖
蒟蒻刚学分块,求调
350314
wannacry_楼主2023/7/24 16:19
#include<cstdio>
#include<cstring>
#include<cmath>
#define int long long
using namespace std;
const int N=1e5+5;
int n,m,q,size,cnt,a[N],p[N],st[N],ed[N],add[N],mul[N],sum[N];
void init(){
	size=sqrt(n);
	if(n%size) cnt=n/size+1; else cnt=n/size;
	for(int i=1;i<=cnt;i++) mul[i]=1,st[i]=(i-1)*size+1,ed[i]=i*size; ed[cnt]=n;
	for(int i=1;i<=n;i++) p[i]=(i-1)/size+1;
	for(int i=1;i<=cnt;i++) for(int j=st[i];j<=ed[i];j++) sum[i]+=a[j];
}
void reset(int x){
	for(int i=st[x];i<=ed[x];i++) a[i]=(a[i]*mul[x]+add[x])%q;
	mul[x]=1,add[x]=0;
}
void update(int l,int r,int k,int type){
	int L=p[l],R=p[r];
	if(type){
		if(L==R){ reset(L);for(int i=l;i<=r;i++) (a[i]*=k)%=q,(sum[L]+=a[i]*(k-1))%=q;}
		else{
			reset(L),reset(R);
			for(int i=l;i<=ed[L];i++) (a[i]*=k)%=q,(sum[L]+=a[i]*(k-1))%=q;
			for(int i=L+1;i<=R-1;i++) (mul[i]*=k)%=q,(add[i]*=k)%=q,(sum[i]*=k)%=q;
			for(int i=st[R];i<=r;i++) (a[i]*=k)%=q,(sum[R]+=a[i]*(k-1))%=q;
		} 
	}
	else{
		if(L==R){ reset(L);for(int i=l;i<=r;i++) (a[i]+=k)%=q,(sum[L]+=k)%=q;}
		else{
			reset(L),reset(R);
			for(int i=l;i<=ed[L];i++) (a[i]+=k)%=q,(sum[L]+=k)%=q;
			for(int i=L+1;i<=R-1;i++) (add[i]+=k)%=q,(sum[i]+=k*size)%=q;
			for(int i=st[R];i<=r;i++) (a[i]+=k)%=q,(sum[R]+=k)%=q;
		}
	}
}
int qu(int l,int r){
	int L=p[l],R=p[r],ans=0;
	if(L==R) for(int i=l;i<=r;i++) (ans+=a[i]*mul[L]+add[L])%=q;
	else{
		for(int i=l;i<=ed[L];i++) (ans+=a[i]*mul[L]+add[L])%=q;
		for(int i=L+1;i<=R-1;i++) (ans+=sum[i])%=q;
		for(int i=st[R];i<=r;i++) (ans+=a[i]*mul[R]+add[R])%=q;
	}
	return ans;
}
signed main(){
	scanf("%lld%lld%lld",&n,&m,&q);
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
	init(); 
	while(m--){
		int flag,l,r,k;
		scanf("%lld",&flag);
		if(flag==1){
			scanf("%lld%lld%lld",&l,&r,&k);
			update(l,r,k,1); 
		}
		else if(flag==2){
			scanf("%lld%lld%lld",&l,&r,&k);
			update(l,r,k,0);
		}
		else{
			scanf("%lld%lld",&l,&r);
			printf("%lld\n",qu(l,r));
		}
	}
	return 0;
}
2023/7/24 16:19
加载中...