#include<iostream>
using namespace std;
const int N = 1e6 + 10;
typedef long long int ll;
const ll inf = 1e20;
ll n, q, tr[4 * N], add[4 * N], val[4 * N];
void push_up(int p)
{
tr[p] = max(tr[2 * p], tr[2 * p + 1]);
}
void push_down(int p, int l, int r)
{
if (val[p] <inf)
{
tr[2 * p] = val[p];
tr[2 * p + 1] = val[p];
val[2 * p] = val[p];
val[2 * p + 1] = val[p];
add[2 * p] = add[2 * p + 1] = add[p] = 0;
val[p] = inf;
}
if(add[p])
{
int mid = (l + r) / 2;
tr[2 * p] += add[p] ;
tr[2 * p + 1] += add[p] ;
add[2 * p] += add[p];
add[2 * p + 1] += add[p];
add[p] = 0;
}
}
void build(int p, int l, int r)
{
val[p] = inf;
if (l == r)
{
cin >> tr[p];
return;
}
int mid = (l + r) / 2;
build(2*p, l, mid);
build(2 * p + 1, mid + 1, r);
push_up(p);
}
void change(int p, int l, int r, int x, int y, ll ad, ll vl)
{
if (x <= l && r <= y)
{
if (vl <inf)
tr[p] = vl,add[p]=0,val[p]=vl;
else
tr[p] += ad,add[p] += ad;
return;
}
push_down(p, l, r);
int mid = (l + r) / 2;
if (x <= mid)change(2*p, l, mid, x, y, ad, vl);
if (y > mid)change(2*p+1, mid + 1, r, x, y, ad, vl);
push_up(p);
}
ll find(int p, int l, int r, int x, int y)
{
if (x <= l && r <= y)
{
return tr[p];
}
push_down(p, l, r);
ll mid = (l + r) / 2, ans = -inf;
if (x <= mid)ans =max(ans,find(2*p, l, mid, x, y));
if (y > mid)ans =max(ans,find(2*p+1, mid + 1, r, x, y));
return ans;
}
int main()
{
cin >> n >> q;
build(1, 1, n);
ll op, l, r, x;
while (q--)
{
cin >> op >> l >> r;
if (op == 1)
{
cin >> x;
change(1, 1, n, l, r, 0, x);
}
else if (op == 2)
{
cin >> x;
change(1, 1, n, l, r, x,inf);
}
else
{
cout << find(1, 1, n, l, r)<<endl;
}
}
}