#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+10;
struct Node{
int sum,add=0,mul=1;//初始化
int l,r;//保存区间
}tree[N*4];//开4倍空间
int n,m,q;//注意:m是模数
int a[N];
void build(int p,int l,int r);
void update(int pos);
void pushdown(int pos);
void do_add(int p,int x,int y,int k);
void do_mul(int p,int x,int y,int k);
int get_sum(int p,int x,int y);
//声明函数
void build(int p,int x,int y){
tree[p].l=x,tree[p].r=y;
tree[p].mul=1;// 初始化mul
if(x==y){//如果区间长度是1,直接返回
tree[p].sum=a[x]%m;
return ;
}
int mid=(x+y)>>1;//分两边建树
build((p<<1),x,mid),build((p<<1)|1,mid+1,y);
update(p);
}
void update(int pos){
tree[pos].sum=(tree[pos<<1].sum+tree[(pos<<1)|1].sum)%m;
return ;
}
void do_add(int p,int x,int y,int k){
if(x<=tree[p].l && tree[p].r<=y){
tree[p].sum=(tree[p].sum+(tree[p].r-tree[p].l+1)*k)%m;
//区间和增加
tree[p].add=(tree[p].add+k)%m;
//懒标记增加
return ;
}
pushdown(p);//更新懒标记
int mid=(tree[p].l+tree[p].r)>>1;//左右区间
if(x<=mid) do_add(p<<1,x,y,k);
if(y>mid) do_add((p<<1)|1,x,y,k);
update(p);
}
void do_mul(int p,int x,int y,int k){
if(x<=tree[p].l && tree[p].r<=y){
tree[p].sum=(tree[p].sum*k)%m;
tree[p].add=(tree[p].add*k)%m;
tree[p].mul=(tree[p].mul*k)%m;
return ;
}
pushdown(p);//更新懒标记
int mid=(tree[p].l+tree[p].r)>>1;//左右区间
if(x<=mid) do_mul(p<<1,x,y,k);
if(y>mid) do_mul((p<<1)|1,x,y,k);
update(p);
}
void pushdown(int pos){
// 先处理乘法标记
tree[pos<<1].sum=(tree[pos<<1].sum*tree[pos].mul)%m;
tree[(pos<<1)|1].sum=(tree[(pos<<1)|1].sum*tree[pos].mul)%m;
tree[pos<<1].mul=(tree[pos<<1].mul*tree[pos].mul)%m;
tree[(pos<<1)|1].mul=(tree[(pos<<1)|1].mul*tree[pos].mul)%m;
tree[pos<<1].add=(tree[pos<<1].add*tree[pos].mul)%m;
tree[(pos<<1)|1].add=(tree[(pos<<1)|1].add*tree[pos].mul)%m;
// 再处理加法标记
tree[pos<<1].sum=(tree[pos<<1].sum+tree[pos].add*(tree[pos<<1].r-tree[pos<<1].l+1))%m;
tree[(pos<<1)|1].sum=(tree[(pos<<1)|1].sum+tree[pos].add*(tree[(pos<<1)|1].r-tree[(pos<<1)|1].l+1))%m;
tree[pos<<1].add=(tree[pos<<1].add+tree[pos].add)%m;
tree[(pos<<1)|1].add=(tree[(pos<<1)|1].add+tree[pos].add)%m;
tree[pos].add=0,tree[pos].mul=1;//清空
}
int get_sum(int p,int x,int y){
if(x<=tree[p].l&&tree[p].r<=y)
return tree[p].sum;//直接取出答案
pushdown(p);
int ans=0;
int mid=(tree[p].l+tree[p].r)>>1;
if(x<=mid) ans=(ans+get_sum(p<<1,x,y))%m;
if(y>mid) ans=(ans+get_sum((p<<1)|1,x,y))%m;
return ans;
}
signed main(){
cin>>n>>q>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
build(1,1,n);//建树
while(q--){
int t,x,y,k;
cin>>t;
if(t==1) cin>>x>>y>>k,do_mul(1,x,y,k);
else if(t==2) cin>>x>>y>>k,do_add(1,x,y,k);
else cin>>x>>y,cout<<get_sum(1,x,y)<<endl;
}
return 0;
}
洛谷能过QWQ