#include<bits/stdc++.h>
#define ls(p) p<<1
#define rs(p) p<<1|1
#define ll long long
#define mid (t[u].l+t[u].r)/2
using namespace std;
const int N=1e6+10;
ll n,m,a,b,c,d,ans[N];
struct tree{
ll l,r,sum,mul,add;
}t[N*4];
void pushup(ll u){
t[u].sum=max(t[ls(u)].sum,t[rs(u)].sum);
}
void build(ll u,ll l,ll r){
t[u].mul=LLONG_MIN;
t[u].l=l,t[u].r=r;
if(l==r){
t[u].sum=ans[l];
return ;
}
build(ls(u),l,mid);
build(rs(u),mid+1,r);
pushup(u);
}
void pushdown(ll u){
if(!t[u].add&&t[u].mul==LLONG_MIN) return ;
if(t[u].mul!=LLONG_MIN){
t[ls(u)].mul+=t[u].mul;
t[rs(u)].mul+=t[u].mul;
t[ls(u)].sum=t[u].mul;
t[rs(u)].sum=t[u].mul;
t[u].mul=LLONG_MIN;
t[u].add=0;
}
if(t[u].add){
t[ls(u)].add+=t[u].add;
t[rs(u)].add+=t[u].add;
t[ls(u)].sum+=t[u].add;
t[rs(u)].sum+=t[u].add;
t[u].add=0;
}
}
void update_add(ll u,ll l,ll r,ll k){
if(t[u].r==0||t[u].l==0) return;
if(l<=t[u].l&&t[u].r<=r){
t[u].add+=k;
t[u].sum+=k;
return ;
}
pushdown(u);
if(l<=mid) update_add(ls(u),l,r,k);
if(r>mid) update_add(rs(u),l,r,k);
pushup(u);
}
void update_mul(ll u,ll l,ll r,ll k){
if(t[u].r==0||t[u].l==0) return;
if(l<=t[u].l&&t[u].r<=r){
t[u].mul=k;
t[u].sum=k;
return ;
}
pushdown(u);
if(l<=mid) update_mul(ls(u),l,r,k);
if(r>mid) update_mul(rs(u),l,r,k);
pushup(u);
}
ll query(ll u,ll l,ll r){
ll res=LLONG_MIN;
if(t[u].l>r||t[u].r<l) return 0;
if(t[u].l>=l&&t[u].r<=r) return t[u].sum;
pushdown(u);
if(l<=mid) res=max(res,query(ls(u),l,r));
if(r>mid) res=max(res,query(rs(u),l,r));
return res;
}
int main(){
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=n;i++) scanf("%lld",&ans[i]);
build(1,1,n);
while(m--){
scanf("%lld",&a);
if(a==1){
scanf("%lld%lld%lld",&b,&c,&d);
update_mul(1,b,c,d);
}
else if(a==2){
scanf("%lld%lld%lld",&b,&c,&d);
update_add(1,b,c,d);
}
else if(a==3){
scanf("%lld%lld",&b,&c);
printf("%lld\n",query(1,b,c));
}
}
return 0;
}