题目
思路
作为线段树模板题,这题主要考查了对lazytag以及先乘后加的使用,
因为是模板,所以这里证明略
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=1e5+5;
int n,m,p;
int a[maxn];
struct node{
int v,mul,add;
}st[maxn*4];
//初始化
void init(int root,int l,int r){
st[root].mul=1,st[root].add=0;
if(l==r) st[root].v=a[l];
else { int mid=l+r>>1;init(root*2,l,mid),init(root*2+1,mid+1,r),st[root].v=st[root*2].v+st[root*2+1].v; }
st[root].v%=p;
return;
}
void pushdown(int root,int l,int r){
int mid=(l+r)/2;
st[root*2].v=(st[root*2].v*st[root].mul+st[root].add*(mid-l+1))%p,st[root*2+1].v=(st[root*2+1].v*st[root].mul+st[root].add*(r-mid))%p,st[root*2].mul=(st[root*2].mul*st[root].mul)%p,st[root*2+1].mul=(st[root*2+1].mul*st[root].mul)%p,st[root*2].add=(st[root*2].add*st[root].mul+st[root].add)%p,st[root*2+1].add=(st[root*2+1].add*st[root].mul+st[root].add)%p,st[root].mul=1,st[root].add=0;
return;
}
//加
void ud1(int root,int stdl,int stdr,int l,int r,int k){
if(r<stdl||stdr<l) return;
if(l<=stdl&&stdr<=r) { st[root].v=(st[root].v*k)%p,st[root].mul=(st[root].mul*k)%p,st[root].add=(st[root].add*k)%p;return; }
pushdown(root,stdl,stdr);
int mid=stdl+stdr>>1;
ud1(root*2,stdl,mid,l,r,k),ud1(root*2+1,mid+1,stdr,l,r,k);
st[root].v=(st[root*2].v+st[root*2+1].v)%p;
return;
}
//乘
void ud2(int root,int stdl,int stdr,int l,int r,int k){
if(r<stdl||stdr<l) return;
if(l<=stdl&&stdr<=r){
st[root].add=(st[root].add+k)%p,st[root].v=(st[root].v+k*(stdr-stdl+1))%p;
return;
}
pushdown(root,stdl,stdr);
int mid=stdl+stdr>>1;
ud2(root*2,stdl,mid,l,r,k),ud2(root*2+1,mid+1,stdr,l,r,k);
st[root].v=(st[root*2].v+st[root*2+1].v)%p;
return;
}
//查询区间和
int query(int root,int stdl,int stdr,int l,int r){
if(r<stdl||stdr<l) return 0;
if(l<=stdl&&stdr<=r) return st[root].v;
pushdown(root,stdl,stdr);
int mid=(stdl+stdr)/2;
return (query(root*2,stdl,mid,l,r)+query(root*2+1,mid+1,stdr,l,r))%p;
}
signed main(){
cin>>n>>m>>p;
for(int i=1;i<=n;i++) cin>>a[i];
init(1,1,n);
while(m--){
int if_case;cin>>if_case;
int x,y,k;
switch (if_case){
case 1:cin>>x>>y>>k;ud1(1,1,n,x,y,k);break;
case 2:cin>>x>>y>>k;ud2(1,1,n,x,y,k);break;
case 3:cin>>x>>y;cout<<query(1,1,n,x,y)<<endl;break;
}
}
return 0;
}
end
完结撒花