题目描述
如题,已知一个数列,你需要进行下面三种操作:
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的结果。
输入输出样例
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
(数据已经过加强^_^)
样例说明:
故输出应为17、2(40 mod 38=2)
就是基本的线段树操作,但是有几个地方要多注意下,也就是我犯错的地方。
1 乘法优先级高于加法
2 初始tag数组时不能用memset把mul全变成1,要在build中赋初始值
3 long long记得最后要改好
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #define ll long long #define il inline #define db double using namespace std; il int gi() { int x=0,y=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') y=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*y; } il ll gl() { ll x=0,y=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') y=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*y; } int n,mm; ll p; ll a[100045],sum[400045]; ll add[400045],mul[400045]; il void build(int rt,int l,int r) { mul[rt]=1; add[rt]=0; int m=(l+r)>>1; if(l==r) { sum[rt]=a[l]; return; } build(rt<<1,l,m); build(rt<<1|1,m+1,r); sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%p; } il void pushdown(int rt,int l,int r) { int m=(l+r)>>1; sum[rt<<1]=(sum[rt<<1]*mul[rt]%p+add[rt]*(m-l+1)%p)%p; sum[rt<<1|1]=(sum[rt<<1|1]*mul[rt]%p+add[rt]*(r-m)%p)%p; mul[rt<<1]=mul[rt<<1]*mul[rt]%p; mul[rt<<1|1]=mul[rt<<1|1]*mul[rt]%p; add[rt<<1]=(add[rt<<1]*mul[rt]%p+add[rt])%p; add[rt<<1|1]=(add[rt<<1|1]*mul[rt]%p+add[rt])%p; mul[rt]=1; add[rt]=0; } il void update1(int rt,int l,int r,int L,int R,ll k) { if(L<=l&&R>=r) { sum[rt]=sum[rt]*k%p; mul[rt]=mul[rt]*k%p; add[rt]=add[rt]*k%p; return; } pushdown(rt,l,r); int m=(l+r)>>1; if(L<=m) update1(rt<<1,l,m,L,R,k); if(R>m) update1(rt<<1|1,m+1,r,L,R,k); sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%p; } il void update2(int rt,int l,int r,int L,int R,ll k) { if(L<=l&&R>=r) { sum[rt]=(sum[rt]+k*(r-l+1))%p; add[rt]=(k+add[rt])%p; return; } pushdown(rt,l,r); int m=(l+r)>>1; if(L<=m) update2(rt<<1,l,m,L,R,k); if(R>m) update2(rt<<1|1,m+1,r,L,R,k); sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%p; } il ll query(int rt,int l,int r,int L,int R) { if(L<=l&&R>=r) return sum[rt]; pushdown(rt,l,r); int m=(l+r)>>1; ll s=0; if(L<=m) s=(s+query(rt<<1,l,m,L,R))%p; if(R>m) s=(s+query(rt<<1|1,m+1,r,L,R))%p; return s%p; } int main() { n=gi(),mm=gi(),p=gl(); for(int i=1;i<=n;i++) a[i]=gl(); build(1,1,n); int x,y,k,r; for(int i=1;i<=mm;i++) { r=gi(); if(r==1) { x=gi(),y=gi(),k=gl(); update1(1,1,n,x,y,k); } if(r==2) { x=gi(),y=gi(),k=gl(); update2(1,1,n,x,y,k); } if(r==3) { x=gi(),y=gi(); printf("%lld ",query(1,1,n,x,y)); } } return 0; }