#include<bits/stdc++.h>
#define IT set<Node>::iterator
using namespace std;
struct Node
{
int l,r;
mutable int v;
Node(int L,int R=-1,int V=0) : l(L),r(R),v(V) {}
bool operator < (const Node &ano) const
{
return l<ano.l;
}
};
set<Node> s;
IT split(int pos)
{
IT it=s.lower_bound(Node(pos));
if(it!=s.end() && it->l==pos)
{
return it;
}
it--;
int L=it->l,R=it->r,V=it->v;
s.erase(it);
s.insert(Node(L,pos-1,V));
return s.insert(Node(pos,R,V)).first;
}
void change(int l,int r,int v)
{
IT itr=split(r+1),itl=split(l);
s.erase(itl,itr);
s.insert(Node(l,r,v));
}
void change2(int l,int r,int v)
{
IT itr=split(r+1),itl=split(l);
for(; itl!=itr; itl++)
{
itl->v=itl->v+v;
}
}
int ask(int l,int r)
{
int ans=-0x3f3f3f3f;
IT itr=split(r+1),itl=split(l);
for(; itl!=itr; itl++)
{
ans=max(ans,itl->v);
}
return ans;
}
int n,T,m,l,r,c,op;
int main()
{
cin>>n>>m;
for(int i=1; i<=n; i++)
{
cin>>c;
s.insert(Node(i,i,c));
}
while(m--)
{
cin>>op>>l>>r;
if(l>r)
{
swap(l,r);
}
if(op==1)
{
cin>>c;
change(l,r,c);
}
else if(op==2)
{
cin>>c;
change2(l,r,c);
}
else
{
cout<<ask(l,r)<<"\n";
}
}
return 0;
}