#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
#define root 1,n,1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define int long long
const int N=1e6+10;
int n,k,a[N],q;
struct node
{
int l,r;
int add=0,sum,mul=1;
void init(int l_,int r_)
{
l=l_;
r=r_;
add=0;
mul=1;
sum=a[l];
}
}z[N];
void color(int rt,int v,int k)
{
z[rt].mul*=k;
z[rt].sum*=k;
z[rt].add*=k;
z[rt].add+=v;
z[rt].sum+=(z[rt].r-z[rt].l+1)*v;
}
void pushdown(int rt)
{
if(z[rt].mul!=1||z[rt].add!=0)
{
color(rt<<1,z[rt].add,z[rt].mul);
color(rt<<1|1,z[rt].add,z[rt].mul);
z[rt].mul=1;
z[rt].add=0;
}
}
node operator+(const node &l,const node &r)
{
node p;
p.l=l.l;
p.r=r.r;
p.sum=l.sum+r.sum;
p.add=0;
p.mul=1;
return p;
}
void update(int rt)
{
z[rt]=z[rt<<1]+z[rt<<1|1];
}
void build(int l,int r,int rt)
{
if(l==r)
{
z[rt].init(l,r);
return;
}
int m=l+r>>1;
build(lson);
build(rson);
update(rt);
}
void modify(int l,int r,int rt,int nowl,int nowr,int v,int k)
{
if(nowl<=l&&r<=nowr)
{
color(rt,v,k);
return;
}
pushdown(rt);
int m=l+r>>1;
if(nowl<=m)modify(lson,nowl,nowr,v,k);
if(nowr>m) modify(rson,nowl,nowr,v,k);
update(rt);
}
node query(int l,int r,int rt,int nowl,int nowr)
{
if(nowl<=l&&r<=nowr)
{
return z[rt];
}
pushdown(rt);
int m=l+r>>1;
if(nowl<=m)
{
if(nowr>m)return query(lson,nowl,nowr)+query(rson,nowl,nowr);
else return query(lson,nowl,nowr);
}
else return query(rson,nowl,nowr);
}
signed main()
{
cin>>n>>k>>q;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
build(1,n,1);
for(int i=1;i<=k;i++)
{
int op;
cin>>op;
if(op==1)
{
int l,r,v;
cin>>l>>r>>v;
modify(root,l,r,0,v);
}
if(op==2)
{
int l,r,v;
scanf("%d%d%d",&l,&r,&v);
modify(root,l,r,v,1);
}
if(op==3)
{
int l,r;
cin>>l>>r;
cout<<query(root,l,r).sum%q<<endl;
}
}
return 0;
}