#include <iostream>
#define int long long
#define ls(p) (p << 1)
#define rs(p) (p << 1 | 1)
using namespace std;
const int N = 1e6 + 5;
int t1[N << 2], t2[N << 2];
int t[N << 2], inf = 1145148100;
int n, m;
void cover(int p, int l, int r, int k)
{
if (k == -inf) return;
t1[p] = 0;
t2[p] = t[p] = k;
}
void add(int p, int l, int r, int k)
{
if (k == 0) return;
int mid = (l + r) >> 1;
cover(ls(p), l, mid + 1, t2[p]);
cover(rs(p), mid + 1, r, t2[p]);
t1[p] += k;
t[p] += k;
}
void push_down(int p, int l, int r)
{
int mid = (l + r) >> 1;
cover(ls(p), l, mid, t2[p]);
cover(rs(p), mid + 1, r, t2[p]);
add(ls(p), l, mid, t1[p]);
add(rs(p), mid + 1, r, t1[p]);
t2[p] = -inf, t1[p] = 0;
}
void build(int p, int l, int r)
{
if (l == r)
{
scanf("%lld", &t[p]);
return;
}
int mid = (l + r) >> 1;
build(ls(p), l, mid);
build(rs(p), mid + 1, r);
t[p] = max(t[ls(p)], t[rs(p)]);
}
void update(int x, int y, int op, int k, int p, int l, int r)
{
if (x <= l && r <= y)
{
if (op == 1) cover(p, l, r, k);
if (op == 2) add(p, l, r, k);
return;
}
push_down(p, l, r);
int mid = (l + r) >> 1;
if (x <= mid) update(x, y, op, k, ls(p), l, mid);
if (y > mid) update(x, y, op, k, rs(p), mid + 1, r);
t[p] = max(t[ls(p)], t[rs(p)]);
}
int query(int x, int y, int p, int l, int r)
{
if (x <= l && r <= y) return t[p];
push_down(p, l, r);
int res = -inf;
int mid = (l + r) >> 1;
if (x <= mid) res = max(res, query(x, y, ls(p), l, mid));
if (y > mid) res = max(res, query(x, y, rs(p), mid + 1, r));
return res;
}
signed main()
{
scanf("%lld%lld", &n, &m);
build(1, 1, n);
for (int i = 1; i <= n * 4; i ++ ) t2[i] = -inf;
int op, x, y, k;
while (m -- )
{
scanf("%lld%lld%lld", &op, &x, &y);
if (op <= 2) scanf("%lld", &k), update(x, y, op, k, 1, 1, n);
else printf("%lld\n", query(x, y, 1, 1, n));
}
return 0;
}