之後的代碼講解下回見!
#pragma GCC optimize(3)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <stdio.h>
#define N 100500
using namespace std;
long long MOD,n,m,k,a[N],size[N<<2],add[N<<2],mul[N<<2];
int fuck,x,y;
long long val[4*N];
inline void Build_tree(int left ,int right,int order)
{
mul[order]=1;
if(left==right){val[order]=a[left];size[order]=1;return ;}
int mid=(left+right) >> 1;
Build_tree(left,mid,order<<1);
Build_tree(mid+1,right,order<<1|1);
val[order]=val[order<<1]+val[order<<1|1];
size[order]=size[order<<1]+size[order<<1|1];
}
inline void Pushdown(int now)
{
if( !add[now] && !mul[now]) return ;
add[now<<1]=add[now<<1]*mul[now]%MOD+add[now];
add[now<<1|1]=add[now<<1|1]*mul[now]%MOD+add[now];
mul[now<<1]=mul[now<<1]*mul[now]%MOD;
mul[now<<1|1]=mul[now<<1|1]*mul[now]%MOD;
val[now<<1]=(val[now<<1]*mul[now]+add[now]*size[now<<1])%MOD;
val[now<<1|1]=(val[now<<1|1]*mul[now]+add[now]*size[now<<1|1])%MOD;
add[now]=0; mul[now]=1;
}
inline void adddata(int order,int nowleft,int nowright,int left,int right,long long mark)
{
if(nowleft > right || nowright < left)return ;
if(nowleft >=left && nowright <= right){add[order]+=mark;val[order]=(val[order]+size[order]*mark)%MOD;return ;}
int mid=(nowleft+nowright) >> 1;
Pushdown(order);
adddata(order<<1,nowleft,mid,left,right,mark);
adddata(order<<1|1,mid+1,nowright,left,right,mark);
val[order]=val[order<<1]+val[order<<1|1];
}
inline void indata(int order,int nowleft,int nowright,int left,int right,long long mark)
{
if(nowleft > right || nowright < left)return ;
if(nowleft >=left && nowright <= right){mul[order]*=mark;add[order]*=mark;val[order]=(val[order]*mark)%MOD;return ;}
int mid=(nowleft+nowright)>>1;
Pushdown(order);
indata(order<<1,nowleft,mid,left,right,mark);
indata(order<<1|1,mid+1,nowright,left,right,mark);
val[order]=val[order<<1]+val[order<<1|1];
}
inline long long query(int now,int nowleft,int nowright,int left,int right)
{
if(nowleft > right || nowright < left)return 0;
if(nowleft >=left && nowright <= right)return val[now];
Pushdown(now);
int mid=(nowleft+nowright) >> 1;
return (query(now<<1, nowleft,mid,left,right)+query(now<<1|1,mid+1,nowright,left,right))%MOD;
}
inline long long read()
{
long long x=0;
char c=getchar();
bool flag=0;
while(c<'0'||c>'9'){if(c=='-')flag=1; c=getchar();}
while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
return flag?-x:x;
}
int main()
{
n=read();m=read();MOD=read();
for(int i=1; i<=n; i++) a[i]=read();
Build_tree(1,n,1);
for(int i=1; i<=m; i++)
{
scanf("%d%d%d",&fuck,&x,&y);
if(fuck==1){k=read();indata(1,1,n,x,y,k);}
else if(fuck==2){k=read();adddata(1,1,n,x,y,k);}
else printf("%lld\n",query(1,1,n,x,y)%MOD);
}
return 0;
}