题目描述:
老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。
有长为N的数列,不妨设为a1,a2,…,aN 。有如下三种操作形式:
(1)把数列中的一段数全部乘一个值;
(2)把数列中的一段数全部加一个值;
(3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值。
题解:
线段树的基本操作。
但是注意lazy标记下传时乘与加的先后顺序。
我这里是先乘后加。
附上代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int N=400100; int n,m,a[N>>2]; long long p,tag[N],tag2[N],sum[N]; void pushup(int k) { sum[k]=(sum[k<<1]+sum[k<<1|1])%p; } void build(int l,int r,int k) { tag2[k]=1; if(l==r) { sum[k]=a[l]%p; return; } int mid=(l+r)>>1; build(l,mid,k<<1); build(mid+1,r,k<<1|1); pushup(k); } void lazy(int l,int r,int k,int len) { (tag[k]+=len)%=p; sum[k]=(sum[k]+1ll*(r-l+1)*len)%p; } void lazy2(int l,int r,int k,int len) { (tag[k]*=len)%=p; (tag2[k]*=len)%=p; sum[k]=(sum[k]*len)%p; } void pushdown(int l,int r,int k) { int mid=(l+r)>>1; if(tag2[k]!=1) { lazy2(l,mid,k<<1,tag2[k]); lazy2(mid+1,r,k<<1|1,tag2[k]); tag2[k]=1; } if(tag[k]!=0) { lazy(l,mid,k<<1,tag[k]); lazy(mid+1,r,k<<1|1,tag[k]); tag[k]=0; } } void update1(int l,int r,int x,int y,int k,int len) { if(x<=l&&r<=y) { sum[k]=(sum[k]*len)%p; (tag[k]*=len)%=p; (tag2[k]*=len)%=p; return; } pushdown(l,r,k); int mid=(l+r)>>1; if(mid>=x) update1(l,mid,x,y,k<<1,len); if(mid<y) update1(mid+1,r,x,y,k<<1|1,len); pushup(k); } void update2(int l,int r,int x,int y,int k,int len) { if(x<=l&&r<=y) { sum[k]=(sum[k]+(r-l+1)*len)%p; (tag[k]+=len)%=p; return; } pushdown(l,r,k); int mid=(l+r)>>1; if(mid>=x) update2(l,mid,x,y,k<<1,len); if(mid<y) update2(mid+1,r,x,y,k<<1|1,len); pushup(k); } long long query(int l,int r,int x,int y,int k) { if(x<=l&&r<=y) return sum[k]; pushdown(l,r,k); int mid=(l+r)>>1; long long ans=0; if(mid>=x) ans=(ans+query(l,mid,x,y,k<<1))%p; if(mid<y) ans=(ans+query(mid+1,r,x,y,k<<1|1))%p; return ans; } int main() { scanf("%d%lld",&n,&p); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,n,1); scanf("%d",&m); for(int i=1;i<=m;i++) { int k,x,y,s; scanf("%d",&s); if(s==1) { scanf("%d%d%d",&x,&y,&k); update1(1,n,x,y,1,k); } if(s==2) { scanf("%d%d%d",&x,&y,&k); update2(1,n,x,y,1,k); } if(s==3) { scanf("%d%d",&x,&y); printf("%lld ",query(1,n,x,y,1)); } } }