#include <bits/stdc++.h>
using namespace std;
int n,m,op,ll,rr;
long long a[1000050],segtree[4000050],change[4000050],add[4000050],xx;
bool p[4000050];
void build_tree(int l,int r,int i)
{
if(l==r)
{
segtree[i]=a[l];
}
else
{
int mid=(l+r)>>1;
build_tree(l,mid,i<<1);
build_tree(mid+1,r,i<<1|1);
segtree[i]=max(segtree[i<<1],segtree[i<<1|1]);
}
return;
}
void lazydown(int l,int r,int i)
{
if(p[i]==1)
{
p[i<<1]=1;
p[i<<1|1]=1;
change[i<<1]=change[i];
change[i<<1|1]=change[i];
segtree[i<<1]=change[i];
segtree[i<<1|1]=change[i];
p[i]=0;
p[i<<1]=1;
p[i<<1|1]=1;
add[i<<1]=0;
add[i<<1|1]=0;
}
else
{
add[i<<1]+=add[i];
add[i<<1|1]+=add[i];
segtree[i<<1]+=add[i];
segtree[i<<1|1]+=add[i];
add[i]=0;
}
return;
}
void updata_change(int l,int r,int i,int q,int w,long long c)
{
if(q<=l&&w>=r)
{
change[i]=c;
segtree[i]=c;
add[i]=0;
p[i]=1;
}
else
{
lazydown(l,r,i);
int mid=(l+r)>>1;
if(q<=mid)updata_change(l,mid,i<<1,q,w,c);
if(w>mid)updata_change(mid+1,r,i<<1|1,q,w,c);
segtree[i]=max(segtree[i<<1],segtree[i<<1|1]);
}
return;
}
void updata_add(int l,int r,int i,int q,int w,long long ad)
{
if(q<=l&&w>=r)
{
add[i]+=ad;
segtree[i]+=ad;
}
else
{
lazydown(l,r,i);
int mid=(l+r)>>1;
if(q<=mid)updata_add(l,mid,i<<1,q,w,ad);
if(w>mid)updata_add(mid+1,r,i<<1|1,q,w,ad);
segtree[i]=max(segtree[i<<1],segtree[i<<1|1]);
}
return;
}
long long query_segtree(int l,int r,int i,int q,int w)
{
if(q<=l&&w>=r)
{
return segtree[i];
}
else
{
lazydown(l,r,i);
int mid=(l+r)>>1;
long long ans=(long long)-(1e19);
if(q<=mid)ans=max(ans,query_segtree(l,mid,i<<1,q,w));
if(w>mid)ans=max(ans,query_segtree(mid+1,r,i<<1|1,q,w));
return ans;
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
build_tree(1,n,1);
for(int i=1;i<=40;i++)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%lld",&ll,&rr,&xx);
updata_change(1,n,1,ll,rr,xx);
}
else
if(op==2)
{
scanf("%d%d%lld",&ll,&rr,&xx);
updata_add(1,n,1,ll,rr,xx);
}
else
{
scanf("%d%d",&ll,&rr);
printf("%lld\n",query_segtree(1,n,1,ll,rr));
}
}
return 0;
}