线段树 2
题目描述 如题,已知一个数列,你需要进行下面三种操作: 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的结果。 输入输出样例 输入样例#1: 5 5 38 1 5 4 2 3 2 1 4 1 3 2 5 1 2 4 2 2 3 5 5 3 1 4 输出样例#1: 17 2 时空限制:1000ms,128M 数据规模: 对于30%的数据:N<=8,M<=10 对于70%的数据:N<=1000,M<=10000 对于100%的数据:N<=100000,M<=100000 (数据已经过加强^_^)
1 #include<iostream> 2 #include<cstdio> 3 #define ll long long 4 using namespace std; 5 const ll N=100002; 6 ll n,mod,a[N],add[N*10],mul[N*10],sum[N*10]; 7 ll m,op,x,y,k; 8 void build(ll o,ll l,ll r) 9 { 10 mul[o]=1;add[o]=0; 11 if(l==r) 12 { 13 sum[o]=a[l]%mod; 14 return; 15 } 16 ll mid=(l+r)>>1; 17 build(o<<1,l,mid);build(o<<1|1,mid+1,r); 18 sum[o]=(sum[o<<1]+sum[o<<1|1])%mod; 19 } 20 void down(ll o,ll l,ll r,ll mid) 21 { 22 if(add[o]==0 && mul[o]==1) return; 23 add[o<<1]=(add[o<<1]*mul[o]+add[o])%mod; 24 mul[o<<1]=mul[o<<1]*mul[o]%mod; 25 sum[o<<1]=(sum[o<<1]*mul[o]%mod+add[o]*(mid-l+1)%mod)%mod; 26 27 add[o<<1|1]=(add[o<<1|1]*mul[o]+add[o])%mod; 28 mul[o<<1|1]=mul[o<<1|1]*mul[o]%mod; 29 sum[o<<1|1]=(sum[o<<1|1]*mul[o]+add[o]*(r-(mid+1)+1))%mod; 30 31 add[o]=0;mul[o]=1; 32 } 33 void Mul(ll o,ll l,ll r,ll x,ll y,ll k) 34 { 35 if(x<=l && y>=r) 36 { 37 add[o]=add[o]%mod*k%mod; 38 sum[o]=sum[o]*k%mod%mod; 39 mul[o]=mul[o]*k%mod; 40 return; 41 } 42 ll mid=(l+r)>>1; 43 down(o,l,r,mid); 44 if(x<=mid) Mul(o<<1,l,mid,x,y,k); 45 if(y>=mid+1) Mul(o<<1|1,mid+1,r,x,y,k); 46 sum[o]=(sum[o<<1]+sum[o<<1|1])%mod; 47 } 48 void Add(ll o,ll l,ll r,ll x,ll y,ll k) 49 { 50 if(x<=l && y>=r) 51 { 52 add[o]=(add[o]+k)%mod; 53 sum[o]=(sum[o]+k*(r-l+1)%mod)%mod; 54 return; 55 } 56 ll mid=(l+r)>>1; 57 down(o,l,r,mid); 58 if(x<=mid) Add(o<<1,l,mid,x,y,k); 59 if(y>=mid+1) Add(o<<1|1,mid+1,r,x,y,k); 60 sum[o]=(sum[o<<1]+sum[o<<1|1])%mod; 61 } 62 ll query(ll o,ll l,ll r,ll x,ll y) 63 { 64 if(x<=l && y>=r) 65 { 66 return sum[o]; 67 } 68 ll tot=0,mid=(l+r)>>1; 69 down(o,l,r,mid); 70 if(x<=mid) tot=(tot+query(o<<1,l,mid,x,y))%mod; 71 if(y>=mid+1) tot=(tot+query(o<<1|1,mid+1,r,x,y))%mod; 72 return tot; 73 } 74 int main() 75 { 76 scanf("%lld%lld%lld",&n,&m,&mod); 77 for(ll i=1;i<=n;++i) scanf("%lld",&a[i]); 78 build(1,1,n); 79 while(m--) 80 { 81 scanf("%lld%lld%lld",&op,&x,&y); 82 if(op==1) 83 { 84 scanf("%lld",&k); 85 Mul(1,1,n,x,y,k); 86 } 87 if(op==2) 88 { 89 scanf("%lld",&k); 90 Add(1,1,n,x,y,k); 91 } 92 if(op==3) 93 printf("%lld\n",query(1,1,n,x,y)%mod); 94 } 95 return 0; 96 }