//Segment Tree //By AcerMo #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int M=500500; struct Tree { long long int son[2],lazy[2]; long long int mks[3],bond[2]; long long int asum; }tree[M*4]; int num[M]; int n,m,root=0,cnt=1,mod; void pushup(int cur) { int ls=tree[cur].son[0]; int rs=tree[cur].son[1]; tree[cur].bond[0]=tree[ls].bond[0]; tree[cur].bond[1]=tree[rs].bond[1]; tree[cur].asum=tree[ls].asum+tree[rs].asum; } void built(int L,int R,int cur) { tree[cur].lazy[0]=0;tree[cur].lazy[1]=1; if (R==L) { tree[cur].asum=num[L]; tree[cur].son[0]=tree[cur].son[1]=-1; tree[cur].bond[0]=tree[cur].bond[1]=L; return ; } tree[cur].son[0]=cnt++; tree[cur].son[1]=cnt++; int mid=(L+R)>>1; built(L,mid,tree[cur].son[0]); built(mid+1,R,tree[cur].son[1]); pushup(cur); } void pushdown(int cur) { int lson=tree[cur].son[0], rson=tree[cur].son[1]; tree[lson].asum=(tree[lson].asum*tree[cur].lazy[1]+tree[cur].lazy[0]*(tree[lson].bond[1]-tree[lson].bond[0]+1))%mod; tree[rson].asum=(tree[rson].asum*tree[cur].lazy[1]+tree[cur].lazy[0]*(tree[rson].bond[1]-tree[rson].bond[0]+1))%mod; tree[lson].lazy[1]=(tree[lson].lazy[1]*tree[cur].lazy[1])%mod; tree[rson].lazy[1]=(tree[rson].lazy[1]*tree[cur].lazy[1])%mod; tree[lson].lazy[0]=(tree[lson].lazy[0]*tree[cur].lazy[1]+tree[cur].lazy[0])%mod; tree[rson].lazy[0]=(tree[rson].lazy[0]*tree[cur].lazy[1]+tree[cur].lazy[0])%mod; tree[cur].lazy[1]=1;tree[cur].lazy[0]=0; } void updateadd(int L,int R,int val,int cur) { if (L<=tree[cur].bond[0]&&tree[cur].bond[1]<=R) { tree[cur].asum+=(val*(tree[cur].bond[1]-tree[cur].bond[0]+1)); tree[cur].asum%=mod;tree[cur].lazy[0]+=val;tree[cur].lazy[0]%=mod; return ; } pushdown(cur); int mid=(tree[cur].bond[0]+tree[cur].bond[1])>>1; if (L<=mid) updateadd(L,R,val,tree[cur].son[0]); if (R>mid) updateadd(L,R,val,tree[cur].son[1]); pushup(cur); } void updatemul(int L,int R,int val,int cur) { if (L<=tree[cur].bond[0]&&tree[cur].bond[1]<=R) { tree[cur].asum*=val;tree[cur].asum%=mod; tree[cur].lazy[0]*=val;tree[cur].lazy[0]%=mod; tree[cur].lazy[1]*=val;tree[cur].lazy[1]%=mod; return ; } pushdown(cur); int mid=(tree[cur].bond[0]+tree[cur].bond[1])>>1; if (L<=mid) updatemul(L,R,val,tree[cur].son[0]); if (R>mid) updatemul(L,R,val,tree[cur].son[1]); pushup(cur); } long long int querysum(int L,int R,int cur) { long long int tot=0; if (L<=tree[cur].bond[0]&&tree[cur].bond[1]<=R) return tree[cur].asum; pushdown(cur); int mid=(tree[cur].bond[0]+tree[cur].bond[1])>>1; if (L<=mid) tot+=querysum(L,R,tree[cur].son[0]); if (R>mid) tot+=querysum(L,R,tree[cur].son[1]); return tot%mod; } int main() { scanf("%d %d %d",&n,&m,&mod); for (int i=1;i<=n;i++) scanf("%d",&num[i]),num[i]%=mod; built(1,n,root); while (m--) { int a,b,c,d; scanf("%d",&d); if (d==1) { scanf("%d %d %d",&a,&b,&c); updatemul(a,b,c,root); } else if (d==2) { scanf("%d %d %d",&a,&b,&c); updateadd(a,b,c,root); } else if (d==3) { scanf("%d %d",&a,&b); cout<<querysum(a,b,root)%mod<<endl; } } return 0; }
线段树[模板]区间加乘
猜你喜欢
转载自blog.csdn.net/acerandaker/article/details/80688438
今日推荐
周排行