线段树 区间加和乘 模板

传送门

题目描述

如题,已知一个数列,你需要进行下面三种操作:

1.将某区间每一个数乘上x

2.将某区间每一个数加上x

3.求出某区间每一个数的和

输入输出格式

输入格式:

第一行包含三个整数N、M、P,分别表示该数列数字的个数、操作的总个数和模数。

第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

接下来M行每行包含3或4个整数,表示一个操作,具体如下:

操作1: 格式:1 x y k 含义:将区间[x,y]内每个数乘上k

操作2: 格式:2 x y k 含义:将区间[x,y]内每个数加上k

操作3: 格式:3 x y 含义:输出区间[x,y]内每个数的和对P取模所得的结果

输出格式:

输出包含若干行整数,即为所有操作3的结果。

AC代码:

#include<cstdio>
#include<iostream>
#define ll long long
using namespace std;
const int Maxn=100005;
ll a[Maxn];
struct node{
	ll x,c,m;
	int l,r; 
}t[Maxn*8]; 
int n,m,mod;
inline int lson(int x){
	return x*2;
}
inline int rson(int x){
	return x*2+1;
}
inline int pushup(int rt){
	t[rt].x=(t[lson(rt)].x+t[rson(rt)].x)%mod;
}
inline void build(int l,int r,int rt){
	t[rt].l=l;t[rt].r=r;t[rt].m=1;
	if(l==r){
		t[rt].x=a[l];
		return;
	}
	int mid=l+r>>1;
	build(l,mid,lson(rt));
	build(mid+1,r,rson(rt));
	pushup(rt);
}
inline int len(int rt){
	return t[rt].r-t[rt].l+1;
}
inline void pushdown(int rt){
	if(t[rt].l==t[rt].r)return;
	if(t[rt].c==0&&t[rt].m==1)return;
	t[lson(rt)].m=t[lson(rt)].m*t[rt].m%mod;
	t[rson(rt)].m=t[rson(rt)].m*t[rt].m%mod;
	t[lson(rt)].x=(t[lson(rt)].x*t[rt].m%mod+t[rt].c*len(lson(rt))%mod)%mod;
	t[rson(rt)].x=(t[rson(rt)].x*t[rt].m%mod+t[rt].c*len(rson(rt))%mod)%mod;
	t[lson(rt)].c=(t[lson(rt)].c*t[rt].m%mod+t[rt].c)%mod;
	t[rson(rt)].c=(t[rson(rt)].c*t[rt].m%mod+t[rt].c)%mod;
	t[rt].c=0;t[rt].m=1;
}
inline void update_1(int l,int r,ll x,int rt){
	if(t[rt].l>=l&&t[rt].r<=r){
		t[rt].x=(t[rt].x+x*len(rt)%mod)%mod;
		t[rt].c=(t[rt].c+x)%mod;
		return;
	}
	pushdown(rt);
	int mid=t[rt].l+t[rt].r>>1;
	if(l<=mid){
		update_1(l,r,x,lson(rt));
	}
	if(r>mid){
		update_1(l,r,x,rson(rt));
	}
	pushup(rt);
}
inline void update_2(int l,int r,ll x,int rt){
	if(t[rt].l>=l&&t[rt].r<=r){
		t[rt].x=(t[rt].x*x)%mod;
		t[rt].m=(t[rt].m*x)%mod;
		t[rt].c=(t[rt].c*x)%mod;
		return;
	}
	pushdown(rt);
	int mid=t[rt].l+t[rt].r>>1;
	if(l<=mid){
		update_2(l,r,x,lson(rt));
	}
	if(r>mid){
		update_2(l,r,x,rson(rt));
	}
	pushup(rt);
}
inline ll query(int l,int r,int rt){
	if(t[rt].l>=l&&t[rt].r<=r){
		return t[rt].x%mod;
	}
	pushdown(rt);
	int mid=t[rt].l+t[rt].r>>1;ll ans=0;
	if(l<=mid){
		ans=(ans+query(l,r,lson(rt)))%mod;
	}
	if(r>mid){
		ans=(ans+query(l,r,rson(rt)))%mod;
	}
	return ans;
}
int main(){
	int u,v,inc;ll w;
	scanf("%d%d%d",&n,&m,&mod);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
	}
	build(1,n,1);
	while(m--){
		scanf("%d%d%d",&inc,&u,&v);
		if(inc==1){
			scanf("%lld",&w);
			update_2(u,v,w,1);
		}
		if(inc==2){
			scanf("%lld",&w);
			update_1(u,v,w,1);
		}
		if(inc==3){
			printf("%lld\n",query(u,v,1));
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/lvyanchang/article/details/80710163