#include<iostream>
#define ll long long
#define lson z[rt].son[L],l,mid
#define rson z[rt].son[R],mid+1,r
using namespace std;
const int N=1e6+100;
const int L=0,R=1;
const ll INF=2e18;
struct node{
ll son[2];
ll maxn;
ll addtag;
ll fixtag;
node(){
maxn=fixtag=-INF;
son[0]=son[1]=addtag=0;
}
}z[2*N];
int a[N];
int n,q;
ll cnt,root;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
void updata(ll rt){
z[rt].maxn = max(z[z[rt].son[L]].maxn , z[z[rt].son[R]].maxn);
}
void build(ll &rt,ll l,ll r){
rt = ++cnt;
if(l==r){
z[rt].maxn = a[l];
return;
}
int mid = l + r >> 1;
build(lson);
build(rson);
updata(rt);
}
void fix_tag(ll rt,ll l,ll r,ll v){
z[rt].addtag = 0;
z[rt].fixtag = v;
z[rt].maxn = v;
}
void add_tag(ll rt,ll l, ll r,ll v){
z[rt].addtag += v;
z[rt].maxn += v;
}
void push_down(ll rt,ll l,ll r){
if(z[rt].fixtag != -INF){
int mid = l + r >> 1;
fix_tag(lson,z[rt].fixtag);
fix_tag(rson,z[rt].fixtag);
z[rt].fixtag = -INF;
}
if(z[rt].addtag != 0){
int mid = l + r >> 1;
add_tag(lson,z[rt].addtag);
add_tag(rson,z[rt].addtag);
z[rt].addtag = 0;
}
}
void modify_fix(ll rt,ll l,ll r,int ql,int qr,ll v){
if(ql <= l && r <= qr){
fix_tag(rt,l,r,v);
return;
}
push_down(rt,l,r);
int mid = l + r >> 1;
if(ql <= mid) modify_fix(lson,ql,qr,v);
if(mid+1 <= qr) modify_fix(rson,ql,qr,v);
updata(rt);
}
void modify_add(ll rt,ll l,ll r,int ql,int qr,ll v){
if(ql <= l && r <= qr){
if(z[rt].fixtag != -INF) fix_tag(rt,l,r,v);
add_tag(rt,l,r,v);
return;
}
push_down(rt,l,r);
int mid = l + r >> 1;
if(ql <= mid) modify_add(lson,ql,qr,v);
if(mid+1 <= qr) modify_add(rson,ql,qr,v);
updata(rt);
}
ll query(ll rt,ll l,ll r,int ql,int qr){
if(ql <= l && r <= qr){
return z[rt].maxn;
}
push_down(rt,l,r);
int mid = l + r >> 1;
ll res = -INF;
if(ql <= mid) res = max(query(lson,ql,qr),res);
if(mid+1 <= qr) res = max(query(rson,ql,qr),res);
return res;
}
int main(){
n=read(),q=read();
for(int i=1;i<=n;i++){
a[i]=read();
}
build(root,1,n);
while(q--){
int opt,l,r;
opt=read(),l=read(),r=read();
if(opt==1){
int x=read();
modify_fix(root,1,n,l,r,x);
}
else if(opt==2){
int x=read();
modify_add(root,1,n,l,r,x);
}
else{
cout<<query(root,1,n,l,r)<<"\n";
}
}
return 0;
}