【模板】线段树 2
乘法懒标等于0也要下传,每次乘法操作对加法也要进行
#include<bits/stdc++.h> using namespace std; #define int long long const int maxn=1e5+10; int v[maxn*4],L[maxn*4],R[maxn*4],lazy1[maxn*4],lazy2[maxn*4]; int A[maxn]; int mod; void build(int l,int r,int x) { L[x]=l,R[x]=r; lazy1[x]=1,lazy2[x]=0; //v[x]=0; if(l==r) { v[x]=(A[l])%mod; return ; } int mid=(l+r)/2; build(l,mid,x*2); build(mid+1,r,x*2+1); v[x]=(v[2*x]+v[2*x+1])%mod; } void pushdown(int x) { // if(lazy1[x]): lazy1[x]==0 { v[x*2]=(v[x*2]*lazy1[x])%mod; v[x*2+1]=(v[x*2+1]*lazy1[x])%mod; lazy1[x*2]=(lazy1[x]*lazy1[x*2])%mod; lazy1[x*2+1]=(lazy1[x]*lazy1[x*2+1])%mod; lazy2[x*2]=(lazy1[x]*lazy2[x*2])%mod; lazy2[x*2+1]=(lazy1[x]*lazy2[x*2+1])%mod; lazy1[x]=1; if(lazy2[x]){ v[2*x]=(v[2*x]+lazy2[x]*(R[2*x]-L[2*x]+1)%mod)%mod; v[2*x+1]=(v[2*x+1]+lazy2[x]*(R[2*x+1]-L[2*x+1]+1)%mod)%mod; lazy2[x*2]=(lazy2[x]+lazy2[x*2])%mod; lazy2[x*2+1]=(lazy2[x]+lazy2[x*2+1])%mod; lazy2[x]=0;} } } void update1(int l,int r,int x,int t) { if(l<=L[x]&&R[x]<=r) { v[x]=(v[x]+t*(R[x]-L[x]+1)%mod)%mod; lazy2[x]=(lazy2[x]+t)%mod; return ; } pushdown(x); int mid=(L[x]+R[x])/2; if(l<=mid)update1(l,r,x*2,t); if(r>mid)update1(l,r,x*2+1,t); v[x]=(v[2*x]+v[2*x+1])%mod; } void update2(int l,int r,int x,int t) { if(l<=L[x]&&R[x]<=r) { v[x]=(v[x]*t)%mod; lazy2[x]=(lazy2[x]*t)%mod; lazy1[x]=(lazy1[x]*t)%mod; return ; } pushdown(x); int mid=(L[x]+R[x])/2; if(l<=mid)update2(l,r,x*2,t); if(r>mid)update2(l,r,x*2+1,t); v[x]=(v[2*x]+v[2*x+1])%mod; } int query(int l,int r,int x) { if(l<=L[x]&&R[x]<=r) { // cout<<v[x]<<"QUE"<<endl; return v[x]%mod; } int mid=(L[x]+R[x])/2; int ans=0; pushdown(x); if(l<=mid) ans+=query(l,r,x*2)%mod; if(r>mid) ans=(ans+query(l,r,x*2+1))%mod; return ans%mod; } signed main() { int n,m; int x,y,z,k; //while( //freopen("a.txt","w",stdout); scanf("%lld%lld%lld",&n,&m,&mod); { for(int i=1; i<=n; i++) { scanf("%lld",&A[i]); } build(1,n,1); while(m--) { scanf("%lld",&x); if(x==2) { scanf("%lld%lld%lld",&y,&z,&k); update1(y,z,1,k); } else if(x==1) { scanf("%lld%lld%lld",&y,&z,&k); update2(y,z,1,k); } else { scanf("%lld%lld",&y,&z); cout<<query(y,z,1)<<' '; } } } }