萌新求调QAQ 30pts AC#1 #3 #4
查看原帖
萌新求调QAQ 30pts AC#1 #3 #4
565852
Small_Traveler楼主2023/6/6 17:25
#include<cstdio>
#define ls u<<1
#define rs u<<1|1
using namespace std;
int p,n,m,t[100005*4],a[100005],lazm[100005*4],lazp[100005*4];//t是线段树数组 a是线段树要维护的数组 lazm是乘法标记 lazp是加法标记 
void mat(int u){//维护父节点u 
	t[u]=((t[ls]%p)+(t[rs]%p))%p;
	return;
}
void bud(int u,int L,int R){//建树 
	if(L==R){
		lazm[u]=1;//顺便把乘法标记初始化 
		t[u]=a[L];
		return; 
	}
	int mid=(L+R)>>1;
	bud(ls,L,mid);
	bud(rs,mid+1,R);
	mat(u);
	lazm[u]=1;//顺便把乘法标记给初始化 
	return;
}
void pushdown(int u,int L,int R){//下传lazy标记 
	if(lazm[u]!=1){//*先下传乘法标记,同时把子树的加法和乘法标记都维护了 
		int k=lazm[u]%p;
		lazm[u]=1;
		t[ls]=((t[ls]%p)*(k))%p;
		t[rs]=((t[rs]%p)*(k))%p;
		lazp[ls]*=k%p;//顺便把子树的加法标记维护了 
		lazp[rs]*=k%p;
		lazm[ls]*=k%p;
		lazm[rs]*=k%p;
	}
	if(lazp[u]!=0){//+
		int k=lazp[u],mid=(L+R)>>1;
		lazp[u]=0;
		t[ls]=((t[ls]%p)+(mid-L+1)*k%p)%p;
		t[rs]=((t[rs]%p)+(R-mid)*k%p)%p;
		lazp[ls]%=p;lazp[ls]+=k;
		lazp[rs]%=p;lazp[rs]+=k;
	}
	return;
}
bool in(int l,int r,int L,int R){//l LR r  这个函数用来判断线段树是不是在维护区间内 
	return l<=L&&R<=r;
}
bool out(int l,int r,int L,int R){//LR lr  lr LR 这个函数判断线段树和维护的区间有没有交集 
	return R<l||r<L;
}
void pls(int u,int l,int r,int L,int R,int k){//维护加操作的函数 
	if(in(l,r,L,R)){
		t[u]=((t[u]%p)+((R-L+1)*k)%p)%p;
		lazp[u]+=k;
		return;
	}
	pushdown(u,L,R);
	int mid=(L+R)>>1;
	if(!out(l,r,L,mid)){
		pls(ls,l,r,L,mid,k);
	}
	if(!out(l,r,mid+1,R)){
		pls(rs,l,r,mid+1,R,k);
	}
	mat(u);
	return;
}
void mut(int u,int l,int r,int L,int R,int k){//维护乘法的函数 
	if(in(l,r,L,R)){
		t[u]=((t[u]%p)*(k%p))%p;
		lazp[u]*=k;
		lazm[u]*=k;
		return;
	}
	pushdown(u,L,R);
	int mid=(L+R)>>1;
	if(!out(l,r,L,mid)){
		mut(ls,l,r,L,mid,k);
	}
	if(!out(l,r,mid+1,R)){
		mut(rs,l,r,mid+1,R,k);
	}
	mat(u);
	return;
}
int fid(int u,int l,int r,int L,int R){//查询区间和 
	if(in(l,r,L,R))return t[u]%p;
	pushdown(u,L,R);
	int tep=0,mid=(L+R)>>1;
	if(!out(l,r,L,mid))tep+=(fid(ls,l,r,L,mid));
	if(!out(l,r,mid+1,R))tep=((tep%p)+(fid(rs,l,r,mid+1,R)%p))%p;
	return tep;
}
int main(){
	scanf("%d%d%d",&n,&m,&p);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	bud(1,1,n);
	for(int i=m;i;i--){
		int opt,x,y,k;
		scanf("%d%d%d",&opt,&x,&y);
		if(opt==1){//*
			scanf("%d",&k);
			mut(1,x,y,1,n,k);
		}
		else if(opt==2){//+
			scanf("%d",&k);
			pls(1,x,y,1,n,k);
		}
		else{//return sum[x,y]%p
			printf("%d\n",fid(1,x,y,1,n)%p);
		}
	}
//	for(int i=1;i<=15;i++)printf("%d ",t[i]);
	return 0;
}
2023/6/6 17:25
加载中...