#include<bits/stdc++.h>
#define int long long
using namespace std;
int const N = 1e7;
struct Tree{
int l;
int c;
int m;
}tr[N<<1];
int a[N<<1];
int n,q;
int op;
inline void push_up(int id)
{
tr[id].m=max(tr[id<<1].m,tr[id<<1|1].m);
}
inline void push_add(int id)
{
if(tr[id].l)
{
tr[id<<1].l+=tr[id].l;
tr[id<<1|1].l+=tr[id].l;
tr[id<<1].m+=tr[id].l;
tr[id<<1|1].m+=tr[id].l;
tr[id].l=0;
}
}
inline void push_cover(int id)
{
if(!tr[id].c==-1e7)
{
tr[id<<1].c=tr[id].c;
tr[id<<1|1].c=tr[id].c;
tr[id<<1].m=tr[id].c;
tr[id<<1|1].m=tr[id].c;
tr[id<<1].l=0;
tr[id<<1|1].l=0;
tr[id].c=-1e7;
}
}
inline void push_down(int id)
{
push_add(id);
push_cover(id);
return;
}
inline void build(int id,int l,int r)
{
if(l==r)
{
tr[id].m=a[l];
tr[id].l=0;
tr[id].c=-1e7;
return;
}
int mid = l+r>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
push_up(id);
}
inline void add(int id,int l,int r,int x,int y,int v)
{
if(x<=l&&r<=y)
{
tr[id].l+=v;
tr[id].m+=v;
return;
}
push_down(id);
int mid = l+r>>1;
if(x<=mid)
{
add(id<<1,l,mid,x,y,v);
}
if(y>mid)
{
add(id<<1|1,mid+1,r,x,y,v);
}
push_up(id);
}
inline void cover(int id,int l,int r,int x,int y,int v)
{
if(x<=l&&r<=y)
{
tr[id].l=0;
tr[id].m=v;
tr[id].c=v;
return;
}
push_down(id);
int mid = l+r>>1;
if(x<=mid)
{
cover(id<<1,l,mid,x,y,v);
}
if(y>mid)
{
cover(id<<1|1,mid+1,r,x,y,v);
}
push_up(id);
}
inline int find(int id,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
{
return tr[id].m;
}
push_down(id);
int mid = l+r>>1;
int ans=-1e8;
if(x<=mid)
{
ans=max(ans,find(id<<1,l,mid,x,y));
}
if(y>mid)
{
ans=max(ans,find(id<<1|1,mid+1,r,x,y));
}
return ans;
}
signed main()
{
cin>>n>>q;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
build(1,1,n);
for(int i=1;i<=q;i++)
{
cin>>op;
if(op==1)
{
int l,r,v;
cin>>l>>r>>v;
cover(1,1,n,l,r,v);
}
if(op==2)
{
int l,r,v;
cin>>l>>r>>v;
add(1,1,n,l,r,v);
}
if(op==3)
{
int l,r;
cin>>l>>r;
cout<<find(1,1,n,l,r)<<endl;
}
}
}