#include<iostream>
using namespace std;
const int N=1e6;
const long long Inf=9e18;
class Segment_Tree{
public:
long long a[N+1],tree[4*N+1],lazy_set[4*N+1],lazy_add[4*N+1];
void make_tag(int u,int type,int v){
if(type==1){
tree[u]=v;
lazy_set[u]=v;
lazy_add[u]=0;
}
else{
tree[u]+=v;
if(lazy_set[u]!=Inf)
lazy_set[u]+=v;
else
lazy_add[u]+=v;
}
}
void push_up(int u){
tree[u]=max(tree[u*2],tree[u*2+1]);
}
void push_down(int u){
if(lazy_set[u]!=Inf){
make_tag(u*2,1,lazy_set[u]);
make_tag(u*2+1,1,lazy_set[u]);
lazy_set[u]=Inf;
}
else{
make_tag(u*2,2,lazy_add[u]);
make_tag(u*2+1,2,lazy_add[u]);
lazy_add[u]=0;
}
}
bool in_range(int ll,int rr,int l,int r){
return ll<=l&&r<=rr;
}
bool out_of_range(int ll,int rr,int l,int r){
return r<ll||rr<l;
}
void build(int l,int r,int u){
if(l==r){
tree[u]=a[l];
lazy_set[u]=Inf;
return;
}
int m=(l+r)/2;
build(l,m,u*2);
build(m+1,r,u*2+1);
push_up(u);
}
void update(int ll,int rr,int l,int r,int u,int type,int v){
if(in_range(ll,rr,l,r)){
make_tag(u,type,v);
return;
}
if(out_of_range(ll,rr,l,r))
return;
push_down(u);
int m=(l+r)/2;
update(ll,rr,l,m,u*2,type,v);
update(ll,rr,m+1,r,u*2+1,type,v);
push_up(u);
}
long long query(int ll,int rr,int l,int r,int u){
if(in_range(ll,rr,l,r))
return tree[u];
if(out_of_range(ll,rr,l,r))
return -Inf;
push_down(u);
int m=(l+r)/2;
return max(query(ll,rr,l,m,u*2),query(ll,rr,m+1,r,u*2+1));
}
};
Segment_Tree my;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n,q;
cin>>n>>q;
for(int i=1;i<=n;i++)
cin>>my.a[i];
my.build(1,n,1);
for(;q--;){
int type,l,r,v;
cin>>type>>l>>r;
if(type!=3){
cin>>v;
my.update(l,r,1,n,1,type,v);
}
else
cout<<my.query(l,r,1,n,1)<<'\n';
}
return 0;
}