洛谷上的模板,与一般的线段树没什么太大区别,只是区间操作多了一个乘上一个值,用两个标记数组,下推标记的时候记得先乘后加就ok了
传送门,代码:
#include<bits/stdc++.h> #define ls rt<<1 #define rs rt<<1|1 using namespace std; typedef long long ll; const int N=1e5+7; int n,m; ll seg[N<<2],s1[N<<2],s2[N<<2],a[N],mod; inline ll read() { ll x=0; char ch=getchar(); bool flag=false; while( ch<'0' || ch>'9' ) { if( ch=='-' ) flag=true; ch=getchar(); } while( ch>='0' && ch<='9' ) { x=x*10+ch-'0'; ch=getchar(); } return flag ? -x : x; } inline void pushup(int rt) { seg[rt]=(seg[ls]+seg[rs])%mod; } inline void pushdown(int l,int r,int rt,ll ln,ll rn) { if( s1[rt]!=1 ) { seg[ls]=seg[ls]*s1[rt]%mod; seg[rs]=seg[rs]*s1[rt]%mod; s1[ls]=s1[ls]*s1[rt]%mod; s1[rs]=s1[rs]*s1[rt]%mod; s2[ls]=s2[ls]*s1[rt]%mod; s2[rs]=s2[rs]*s1[rt]%mod; s1[rt]=1; } if( s2[rt]!=0 ) { seg[ls]=(seg[ls]+s2[rt]*ln%mod)%mod; seg[rs]=(seg[rs]+s2[rt]*rn%mod)%mod; s2[ls]=(s2[ls]+s2[rt])%mod; s2[rs]=(s2[rs]+s2[rt])%mod; s2[rt]=0; } } void build(int l,int r,int rt) { s1[rt]=1; if( l==r ) { seg[rt]=a[l]%mod; return ; } int mid=l+r>>1; build(l,mid,ls); build(mid+1,r,rs); pushup(rt); } void update(int l,int r,int rt,int L,int R,ll C,int type) { if( L>r || l>R ) return; if( L<=l && r<=R ) { if( type==1 ) { seg[rt]=seg[rt]*C%mod; s1[rt]=s1[rt]*C%mod; s2[rt]=s2[rt]*C%mod; } else { seg[rt]=(seg[rt]+C*(r-l+1))%mod; s2[rt]=(s2[rt]+C)%mod; } return; } int mid=l+r>>1; pushdown(l,r,rt,mid-l+1,r-mid); if( L<=mid ) update(l,mid,ls,L,R,C,type); if( R>mid ) update(mid+1,r,rs,L,R,C,type); pushup(rt); } ll query(int l,int r,int rt,int L,int R) { if( L>r || R<l ) return 0; if( L<=l && r<=R ) return seg[rt]; int mid=l+r>>1; ll ret=0; pushdown(l,r,rt,mid-l+1,r-mid); if( L<=mid ) ret=(ret+query(l,mid,ls,L,R))%mod; if( R>mid ) ret=(ret+query(mid+1,r,rs,L,R))%mod; return ret%mod; } int main() { n=read(); m=read(); mod=read(); for(int i=1; i<=n; ++i) a[i]=read(); build(1,n,1); int s,x,y; ll z; for(int i=1; i<=m; ++i) { s=read(); if( s==1 ) { x=read(), y=read(), z=read(); update(1,n,1,x,y,z,1); } else if( s==2 ) { x=read(), y=read(), z=read(); update(1,n,1,x,y,z,2); } else { x=read(), y=read(); printf("%lld ",query(1,n,1,x,y)); } } return 0; }
貌似又是一道water题。。。