#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#define ll long long
using namespace std;
const int maxx=100001;
int n,q;
ll c1[maxx],c2[maxx];
ll lowbit(ll x){return x&(-x);}
struct tree{
void add(long long *array,int x,int val){
for(int i=x;i<=n;i+=lowbit(i))
array[i]+=val;
}
long long query(long long *array,int x){
long long ans=0;
for(int i=x;i;i-=lowbit(i))
ans+=array[i];
return ans;
}
}tree;
ll read(){
char x;
while((x=getchar())<'0' || x>'9');
ll u=x-'0';
while((x=getchar())>='0' && x<='9')u=u*10+x-'0';
return u;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
freopen("output.out","w",stdout);
#endif
int i,j,k,m,pre=0;
n=read();q=read();
for(i=1;i<=n;i++){
k=read();
tree.add(c1,i,k-pre);
tree.add(c2,i,(k-pre)*(i-1));
pre=k;
}
while(q--){
k=read();
if(k==1){
i=read();
j=read();
m=read();
tree.add(c1,i,m);
tree.add(c1,j+1,-m);
tree.add(c2,i,m*(i-1));
tree.add(c2,j+1,-m*j);
}
else{
i=read();
j=read();
ll dog=j*tree.query(c1,j)-tree.query(c2,j);
ll sb=(i-1)*tree.query(c1,i-1)-tree.query(c2,i-1);
printf("%lld\n",dog-sb);
}
}
return 0;
}
#include<cstdio>
#include<cstring>
#include<iostream>
#define ls node << 1
#define rs node << 1 | 1
#define maxn 100005
#define For(a, b, c) for(a = b; a <= (int)c; ++a)
using namespace std;
typedef long long LL;
int n, m;
LL tr[maxn << 2], plu[maxn << 2], mut[maxn << 2], p, a[maxn];
inline void push_up(int node){
tr[node] = (tr[ls] + tr[rs]) % p;
}
void build(int node, int l, int r){
mut[node] = 1;
if(l == r){
tr[node] = a[l];
return ;
}
int mid = l + r >> 1;
build(ls, l, mid);
build(rs, mid + 1, r);
push_up(node);
}
inline void add(int node, int l, int r, int x, bool d){
if(!d){
(mut[node] *= x) %= p;
(tr[node] *= x) %= p;
(plu[node] *= x) %= p;
}
else{
(plu[node] += x) %= p;
(tr[node] += (r - l + 1) * x) %= p;
}
}
inline void push_down(int node, int l, int r){
if(mut[node] == 1 && !plu[node]) return ;
int mid = l + r >> 1;
if(mut[node] != 1){
(tr[ls] *= mut[node]) %= p;
(mut[ls] *= mut[node]) %= p;
(plu[ls] *= mut[node]) %= p;
(tr[rs] *= mut[node]) %= p;
(mut[rs] *= mut[node]) %= p;
(plu[rs] *= mut[node]) %= p;
} mut[node] = 1;
if(plu[node]){
(tr[ls] += (mid - l + 1) * plu[node]) %= p;
(plu[ls] += plu[node]) %= p;
(tr[rs] += (r - mid) * plu[node]) %= p;
(plu[rs] += plu[node]) %= p;
} plu[node] = 0;
}
void updata(int node, int l, int r, int z, int y, int x, bool d){
if(l >= z && r <= y){
add(node, l, r, x, d);
return ;
}
push_down(node, l, r);
int mid = l + r >> 1;
if(y <= mid) updata(ls, l, mid, z, y, x, d);
else if(z > mid) updata(rs, mid + 1, r, z, y, x, d);
else{
updata(ls, l, mid, z, y, x, d);
updata(rs, mid + 1, r, z, y, x, d);
}
push_up(node);
}
LL query(int node, int l, int r, int z, int y){
if(l >= z && r <= y) return tr[node];
push_down(node, l, r);
int mid = l + r >> 1;
if(y <= mid) return query(ls, l, mid, z, y);
else if(z > mid) return query(rs, mid + 1, r, z, y);
return (query(ls, l, mid, z, y) + query(rs, mid + 1, r, z, y)) % p;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("st.in", "r", stdin);
freopen("st.out","w",stdout);
#endif
int i, u, x, y, k;
scanf("%d%d%lld", &n, &m, &p);
For(i, 1, n) scanf("%lld", &a[i]);
build(1, 1, n);
while(m--){
scanf("%d", &u);
if(u == 1){
scanf("%d%d%d", &x, &y, &k);
updata(1, 1, n, x, y, k, 0);
}
else if(u == 2){
scanf("%d%d%d", &x, &y, &k);
updata(1, 1, n, x, y, k, 1);
}
else{
scanf("%d%d", &x, &y);
printf("%lld\n", query(1, 1, n, x, y));
}
}
return 0;
}
#include<cstdio>
#include<cstring>
#include<iostream>
#define ls node << 1
#define rs node << 1 | 1
#define maxn 100005
#define For(a, b, c) for(a = b; a <= (int)c; ++a)
using namespace std;
typedef long long LL;
int n, m;
LL tr[maxn << 2], plu[maxn << 2], mut[maxn << 2], p, a[maxn];
inline void push_up(int node){
tr[node] = (tr[ls] + tr[rs]) % p;
}
void build(int node, int l, int r){
mut[node] = 1;
if(l == r){
tr[node] = a[l];
return ;
}
int mid = l + r >> 1;
build(ls, l, mid);
build(rs, mid + 1, r);
push_up(node);
}
inline void add(int node, int l, int r, int x, bool d){
if(!d){
(mut[node] *= x) %= p;
(tr[node] *= x) %= p;
(plu[node] *= x) %= p;
}
else{
(plu[node] += x) %= p;
(tr[node] += (r - l + 1) * x) %= p;
}
}
inline void push_down(int node, int l, int r){
if(mut[node] == 1 && !plu[node]) return ;
int mid = l + r >> 1;
if(mut[node] != 1){
(tr[ls] *= mut[node]) %= p;
(mut[ls] *= mut[node]) %= p;
(plu[ls] *= mut[node]) %= p;
(tr[rs] *= mut[node]) %= p;
(mut[rs] *= mut[node]) %= p;
(plu[rs] *= mut[node]) %= p;
} mut[node] = 1;
if(plu[node]){
(tr[ls] += (mid - l + 1) * plu[node]) %= p;
(plu[ls] += plu[node]) %= p;
(tr[rs] += (r - mid) * plu[node]) %= p;
(plu[rs] += plu[node]) %= p;
} plu[node] = 0;
}
void updata(int node, int l, int r, int z, int y, int x, bool d){
if(l >= z && r <= y){
add(node, l, r, x, d);
return ;
}
push_down(node, l, r);
int mid = l + r >> 1;
if(y <= mid) updata(ls, l, mid, z, y, x, d);
else if(z > mid) updata(rs, mid + 1, r, z, y, x, d);
else{
updata(ls, l, mid, z, y, x, d);
updata(rs, mid + 1, r, z, y, x, d);
}
push_up(node);
}
LL query(int node, int l, int r, int z, int y){
if(l >= z && r <= y) return tr[node];
push_down(node, l, r);
int mid = l + r >> 1;
if(y <= mid) return query(ls, l, mid, z, y);
else if(z > mid) return query(rs, mid + 1, r, z, y);
return (query(ls, l, mid, z, y) + query(rs, mid + 1, r, z, y)) % p;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("st.in", "r", stdin);
freopen("st.out","w",stdout);
#endif
int i, u, x, y, k;
scanf("%d%d%lld", &n, &m, &p);
For(i, 1, n) scanf("%lld", &a[i]);
build(1, 1, n);
while(m--){
scanf("%d", &u);
if(u == 1){
scanf("%d%d%d", &x, &y, &k);
updata(1, 1, n, x, y, k, 0);
}
else if(u == 2){
scanf("%d%d%d", &x, &y, &k);
updata(1, 1, n, x, y, k, 1);
}
else{
scanf("%d%d", &x, &y);
printf("%lld\n", query(1, 1, n, x, y));
}
}
return 0;
}