线段树
懒标记+乘法
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define int long long
using namespace std;
int n,m;
int ans,p,num[3000100];
struct Node{
int l,r,num;
int sum,lazy,mul;
} tr[4000100];
void pushup(int now){
tr[now].sum=(tr[now<<1].sum+tr[now<<1|1].sum)%p;
}
void buildtree(int l,int r,int now){
tr[now].l=l;
tr[now].r=r;
tr[now].mul=1;
if(l==r){
scanf("%lld",&tr[now].sum);
return;
}
int mid=(l+r)>>1;
buildtree(l,mid,now<<1);
buildtree(mid+1,r,now<<1|1);
pushup(now);
}
void pushdown(int now){
tr[now<<1].mul=(tr[now<<1].mul*tr[now].mul)%p;
tr[now<<1|1].mul=(tr[now<<1|1].mul*tr[now].mul)%p;
tr[now<<1].lazy=(tr[now<<1].lazy*tr[now].mul+tr[now].lazy)%p;
tr[now<<1|1].lazy=(tr[now<<1|1].lazy*tr[now].mul+tr[now].lazy)%p;
tr[now<<1].sum=(tr[now<<1].sum*tr[now].mul+(tr[now<<1].r-tr[now<<1].l+1)*tr[now].lazy)%p;
tr[now<<1|1].sum=(tr[now<<1|1].sum*tr[now].mul+(tr[now<<1|1].r-tr[now<<1|1].l+1)*tr[now].lazy)%p;
tr[now].lazy=0;
tr[now].mul=1;
}
void update(int l,int r,int now,int val){
if(tr[now].l==l&&tr[now].r==r){
tr[now].lazy=(tr[now].lazy+val)%p;
tr[now].sum=(tr[now].sum+(tr[now].r-tr[now].l+1)*val)%p;
return;
}
if(tr[now].lazy||tr[now].mul!=1) pushdown(now);
int mid=(tr[now].l+tr[now].r)>>1;
if(l>mid) update(l,r,now<<1|1,val);
else if(mid>=r) update(l,r,now<<1,val);
else{
update(l,mid,now<<1,val);
update(mid+1,r,now<<1|1,val);
}
pushup(now);
}
void multi(int l,int r,int now,int val){
if(tr[now].l==l&&tr[now].r==r){
tr[now].lazy=(tr[now].lazy*val)%p;
tr[now].mul=(tr[now].mul*val)%p;
tr[now].sum=(tr[now].sum*val)%p;
return;
}
if(tr[now].lazy||tr[now].mul!=1) pushdown(now);
int mid=(tr[now].l+tr[now].r)>>1;
if(l>mid) multi(l,r,now<<1|1,val);
else if(mid>=r) multi(l,r,now<<1,val);
else{
multi(l,mid,now<<1,val);
multi(mid+1,r,now<<1|1,val);
}
pushup(now);
}
void check(int l,int r,int now){
if(tr[now].l==l&&tr[now].r==r){
ans=(tr[now].sum+ans)%p;
return;
}
if(tr[now].lazy||tr[now].mul!=1) pushdown(now);
int mid=(tr[now].l+tr[now].r)>>1;
if(l>mid) check(l,r,now<<1|1);
else if(mid>=r) check(l,r,now<<1);
else{
check(l,mid,now<<1);
check(mid+1,r,now<<1|1);
}
pushup(now);
}
signed main(){
int k;
scanf("%d%d%lld",&n,&m,&p);
buildtree(1,n,1);
for(int i=1,cas,x,y;i<=m;i++){
scanf("%d%d%d",&cas,&x,&y);
if(cas==1){
scanf("%lld",&k);
multi(x,y,1,k);
}
else if(cas==2){
scanf("%lld",&k);
update(x,y,1,k);
}
else{
ans=0;
check(x,y,1);
printf("%lld\n",ans);
}
}
return 0;
}