#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ls p << 1
#define rs p << 1 | 1
ll n,m,q;
ll a[1000005];
struct edge{
ll maxn,tag1,vis,tag2;
}t[4000005];
void build(ll p,ll l,ll r){
if(l==r){
t[p].maxn=a[l];
return ;
}
ll mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
t[p].maxn=max(t[ls].maxn,t[rs].maxn);
}
void push_down(ll p){
if(t[p].vis){
t[ls].tag1=t[p].tag1;
t[rs].tag1=t[p].tag1;
t[ls].vis=t[p].vis;
t[rs].vis=t[p].vis;
t[rs].maxn=t[p].tag1;
t[ls].maxn=t[p].tag1;
}else{
t[ls].tag2+=t[p].tag2;
t[rs].tag2+=t[p].tag2;
t[ls].maxn+=t[p].tag2;
t[rs].maxn+=t[p].tag2;
t[p].tag2=0;
}
}
void update1(ll p,ll l,ll r,ll tl,ll tr,ll k){
if(tl<=l&&r<=tr){
t[p].vis=1;
t[p].maxn=k;
t[p].tag1=k;
t[p].tag2=0;
return ;
}
push_down(p);
ll mid=(l+r)>>1;
if(tl<=mid)
update1(ls,l,mid,tl,tr,k);
if(mid<tr)
update1(rs,mid+1,r,tl,tr,k);
if(t[p].vis)
t[p].tag1=max(t[ls].tag1,t[rs].tag1);
else
t[p].maxn=max(t[ls].maxn,t[rs].maxn);
}
void update2(ll p,ll l,ll r,ll tl,ll tr,ll k){
if(tl<=l&&r<=tr){
if(t[p].vis)
t[p].tag1+=k;
t[p].tag2+=k;
t[p].maxn+=k;
return ;
}
push_down(p);
ll mid=(l+r)>>1;
if(tl<=mid)
update2(ls,l,mid,tl,tr,k);
if(mid<tr)
update2(rs,mid+1,r,tl,tr,k);
if(t[p].vis)
t[p].tag1=max(t[ls].tag1,t[rs].tag1);
else
t[p].maxn=max(t[ls].maxn,t[rs].maxn);
}
ll query(ll p,ll l,ll r,ll tl,ll tr){
if(tl<=l&&r<=tr){
if(t[p].vis)
return t[p].tag1;
return t[p].maxn;
}
ll res=-1145141919;
ll mid=(l+r)>>1;
push_down(p);
if(tl<=mid)
res=max(res,query(ls,l,mid,tl,tr));
if(mid<tr)
res=max(res,query(rs,mid+1,r,tl,tr));
return res;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>q;
for(int i=1;i<=n;i++)
cin>>a[i];
build(1,1,n);
while(q--){
ll opt;
cin>>opt;
if(opt==1){
ll l,r,x;
cin>>l>>r>>x;
update1(1,1,n,l,r,x);
}else if(opt==2){
ll l,r,x;
cin>>l>>r>>x;
update2(1,1,n,l,r,x);
}else{
ll l,r;
cin>>l>>r;
cout<<query(1,1,n,l,r)<<"\n";
}
}
return 0;
}
/*
4 2
10 4 -3 -7
1 1 3 0
3 1 1
*/