30分求助,只有#1#3#4AC了
查看原帖
30分求助,只有#1#3#4AC了
181162
qd_zhanghuali楼主2020/7/28 10:46
#include<cstdio>
using namespace std;
long long int tree[400040],n,m,a[100001],lac[400040],la[400040],x,y,c,v,p;//lac 乘法标记 la加法标记 a原数组 tree线段树
void build(int k,int l,int r){//建树
	if(l==r){
		tree[k]=a[l]%p;
		return;
	}
	int mid=l+r>>1;
	build(k*2,l,mid);
	build(k*2+1,mid+1,r);
	tree[k]=tree[2*k]+tree[2*k+1];
	tree[k]%=p;
	return;
}
void ccc(int k,long long int v){//乘法
	if(lac[k]==0)lac[k]=1;
	lac[k]*=v;
	lac[k]%=p;
	la[k]*=v;
	la[k]%=p;
	tree[k]*=v;
	tree[k]%=p;
}
void add(int k,int l,int r,long long int v){//加法
	la[k]+=v;
	la[k]%=p;
	tree[k]+=(r-l+1)*v;
	tree[k]%=p;
}
void pd(int k,int l,int r){//下传标记
	if(lac[k]!=0){
		int mid=l+r>>1;
		ccc(k*2,lac[k]);
		ccc(k*2+1,lac[k]);
		lac[k]=0;
	}
	if(la[k]!=0){
		int mid=l+r>>1;
		add(k*2,l,mid,la[k]);
		add(k*2+1,mid+1,r,la[k]);
		la[k]=0;
	}
}
void qjj(int k,int l,int r,int x,int y,long long int v){//区间加
	if(x<=l&&r<=y){
		add(k,l,r,v);
		return;
	}
	int mid=l+r>>1;//l,x,mid,r,y
	pd(k,l,r);
	if(x<=mid)qjj(2*k,l,mid,x,y,v);
	if(y>mid)qjj(2*k+1,mid+1,r,x,y,v);
	tree[k]=tree[2*k]+tree[2*k+1];
	tree[k]%=p;
}
void qjc(int k,int l,int r,int x,int y,long long int v){//区间乘
	if(x<=l&&r<=y){
		ccc(k,v);
		return;
	}
	int mid=l+r>>1;//l,x,mid,r,y
	pd(k,l,r);
	if(x<=mid)qjc(2*k,l,mid,x,y,v);
	if(y>mid)qjc(2*k+1,mid+1,r,x,y,v);
	tree[k]=tree[2*k]+tree[2*k+1];
	tree[k]%=p;
}
long long int ask(int k,int l,int r,int x,int y){//区间询问
	if(x<=l&&r<=y){
		return tree[k];
	}
	long long int ans=0;
	int mid=l+r>>1;//l,mid,y,r
	pd(k,l,r);
	if(x<=mid)ans+=ask(k*2,l,mid,x,y);
	if(y>mid)ans+=ask(k*2+1,mid+1,r,x,y);
	return ans%p;
}
int main(){
	scanf("%lld%lld%lld",&n,&m,&p);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	build(1,1,n);
	for(int i=1;i<=m;i++){
		scanf("%lld%lld%lld",&c,&x,&y);
		if(c==2){
			scanf("%lld",&v);
			qjj(1,1,n,x,y,v);
			continue;
		}
		if(c==3){
			printf("%lld\n",ask(1,1,n,x,y));
		}else{
			scanf("%lld",&v);
			qjc(1,1,n,x,y,v);
		}
	}
	return 0;
}
2020/7/28 10:46
加载中...