code:
#include<stdio.h>
#define int long long
int p;//马蜂参考:皎月半洒花
int a[100009];
int t[400009];
int g1[400009];//加法标记
int g2[400009];//乘法标记
inline int read(){//快读
int x=0;
bool f=1;
char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-') f=0;
ch=getchar();
}
while(ch<='9'&&ch>='0'){
x=(x<<3)+(x<<1)+(ch^48);
ch=getchar();
}
return f?x:-x;
}
inline void write(int x){//快写
if(!x){
putchar('0');
return;
}
char F[20];
if(x<0)
putchar('-'),x=-x;
int cnt=0;
while(x)
F[cnt++]=(x%10^48),x/=10;
while(cnt)
putchar(F[--cnt]);
return;
}
inline int ls(int x){
return x<<1;
}
inline int rs(int x){
return x<<1|1;
}
inline void push_up(int x){
t[x]=t[ls(x)]+t[rs(x)];
t[x]%=p;
return;
}
inline void build(int x,int l,int r){
if(l==r){
t[x]=a[l];
return;
}
int mid=(l+r)>>1;
build(ls(x),l,mid);
build(rs(x),mid+1,r);
push_up(x);
return;
}
inline void f(int x,int l,int r,int s1,int s2){
t[x]=(t[x]*s2+s1*(r-l+1))%p;//更新值和标记
g2[x]=(g2[x]*s2)%p;//s1为加法更新值,s2为乘法
g1[x]=(g1[x]*s2+s1)%p;
return;
}
inline void push_down(int x,int l,int r){//下放标记
int mid=(l+r)>>1;
// if(g1[x]!=0&&g2[x]!=1){
// printf("nnd,gwwydsb");
// return;
// }
f(ls(x),l,mid,g1[x],g2[x]);//更新子节点的值和标记
f(rs(x),mid+1,r,g1[x],g2[x]);
g1[x]=0;//标记已经下放完了,直接清掉
g2[x]=1;//要加的数变为0,要乘的数变为1
return;
}
inline void update1(int x,int l,int r,int nl,int nr,int s){//区间加
if(nl<=l&&r<=nr){
f(x,l,r,s,1);//一函数多用,这里直接默认子节点要乘的值为1
return;
}
int mid=(l+r)>>1;
push_down(x,l,r);
if(nl<=mid)
update1(ls(x),l,mid,nl,nr,s);
if(nr>mid)
update1(rs(x),mid+1,r,nl,nr,s);
push_up(x);
return;
}
inline void update2(int x,int l,int r,int nl,int nr,int s){//区间乘
if(nl<=l&&r<=nr){
f(x,l,r,0,s);//默认要加的数为0
return;
}
int mid=(l+r)>>1;
push_down(x,l,r);
if(nl<=mid)
update2(ls(x),l,mid,nl,nr,s);
if(nr>mid)
update2(rs(x),mid+1,r,nl,nr,s);
push_up(x);
return;
}
inline int ask(int x,int l,int r,int nl,int nr){//询问
int ans=0;
if(nl<=l&&r<=nr)
return t[x];
int mid=(l+r)>>1;
push_down(x,l,r);
if(nl<=mid)
ans+=ask(ls(x),l,mid,nl,nr);
if(nr>mid)
ans+=ask(rs(x),mid+1,r,nl,nr);
// push_up(x);
return ans;
}
signed main(){
//
int n=read(),m=read();
p=read();
for(int i=1;i<=n;++i){
a[i]=read();
}
build(1,1,n);
while(m--){
int op=read();
int l=read();
int r=read();
if(op==1){
int k=read();
update2(1,1,n,l,r,k);
}
else if(op==2){
int k=read();
update1(1,1,n,l,r,k);
}
else{
write(ask(1,1,n,l,r)%p);
putchar('\n');
}
}
return 0;
}
全WA