#include<bits/stdc++.h>
using namespace std;
const long long N=10e6+10 , MIN = LONG_LONG_MIN;
typedef long long ll;
long long n,m,a[N];
struct tree
{
ll l,r;
ll sum,add,s;
}tr[4*N];
void build(int u,int l,int r)
{
tr[u] = {l,r,MIN,MIN,MIN};
ll mid = l+r >> 1;
if(l == r) tr[u].sum = a[l];
else{
build(u << 1,l,mid),build(u << 1|1,mid+1,r);
tr[u].sum = max(tr[u << 1].sum , tr[u << 1|1].sum);
}
}
void pushdown_s(int u)
{
auto &a=tr[u],&b=tr[u << 1],&c=tr[u << 1|1];
if(a.s!=MIN){
b.add = c.add = MIN;
b.s=a.s; b.sum = a.s;
c.s=a.s; c.sum = a.s;
a.s=MIN;
}
}
void pushdown_a(int u)
{
auto &a=tr[u],&b=tr[u << 1],&c=tr[u << 1|1];
if(a.add!=MIN){
b.add+=a.add; b.sum += a.add;
c.add+=a.add; c.sum += a.add;
a.add = MIN;
}
}
void update_s(int u,int x,int y,int w)
{
int l = tr[u].l , r = tr[u].r , mid = l+r >> 1;
if(x<=l&&y>=r) {
tr[u].sum = w;
tr[u].s = w;
}
else{
pushdown_s(u);
pushdown_a(u);
if(x<=mid) update_s(u << 1,x,y,w);
if(y>mid) update_s(u << 1|1,x,y,w);
tr[u].sum = max(tr[u << 1].sum,tr[u << 1|1].sum);
}
}
void update_a(ll u,ll x,ll y,ll w)
{
ll l = tr[u].l , r = tr[u].r , mid = l+r >> 1;
if(x<=l&&y>=r) {
tr[u].sum += w;
tr[u].add += w;
}
else{
pushdown_s(u);
pushdown_a(u);
if(x<=mid) update_a(u << 1,x,y,w);
if(y>mid) update_a(u << 1|1,x,y,w);
tr[u].sum = max(tr[u << 1].sum,tr[u << 1|1].sum);
}
}
ll query(ll u,ll x,ll y)
{
ll l = tr[u].l , r = tr[u].r , mid = l+r >> 1;
if(x<=l&&y>=r) return tr[u].sum;
else{
pushdown_s(u);
pushdown_a(u);
long long inf = LONG_LONG_MIN;
if(x<=mid) inf = max(inf,query(u << 1,x,y));
if(y>mid) inf = max(inf,query(u << 1|1,x,y));
return inf ;
}
}
int main()
{
cin >> n >> m;
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
build(1,1,n);
while(m--){
ll op,x,y,k;
scanf("%lld",&op);
if(op == 1){
scanf("%lld%lld%lld",&x,&y,&k);
update_s(1,x,y,k);
}
if(op == 2){
scanf("%lld%lld%lld",&x,&y,&k);
update_a(1,x,y,k);
}
if(op == 3){
scanf("%lld%lld",&x,&y);
printf("%lld\n",query(1,x,y));
}
}
}