#include <iostream>
#define int long long
using namespace std;
const int inf = 9223372036854775807;
const int maxn = 1000005;
int n, q;
int a[maxn];
int w[maxn * 4];
int lzy_1[maxn * 4];
int lzy_2[maxn * 4];
bool ir (int l, int r, int L, int R) {
return (L <= l and r <= R);
}
bool otr (int l, int r, int L, int R) {
return (l > R or r < L);
}
void pushup (const int u) {
w[u] = max (w[u * 2], w[u * 2 + 1]);
return;
}
void maketag (const int u, int x, bool type) {
if (not type) {
if (lzy_2[u] == inf) lzy_1[u] += x;
else lzy_2[u] += x;
w[u] += x;
} else {
lzy_1[u] = 0;
lzy_2[u] = x;
w[u] = x;
}
}
void pushdown (const int u) {
if (lzy_2[u] == inf) {
maketag (u * 2, lzy_1[u], 0);
maketag (u * 2 + 1, lzy_1[u], 0);
lzy_1[u] = 0;
} else {
maketag (u * 2, lzy_2[u], 1);
maketag (u * 2 + 1, lzy_2[u], 1);
lzy_2[u] = inf;
}
}
void build (const int u, int l, int r) {
lzy_2[u] = inf;
if (l == r) {
w[u] = a[l];
return;
}
int m = (l + r) >> 1;
build (u * 2, l, m);
build (u * 2 + 1, m + 1, r);
pushup (u);
return;
}
int query (int l, int r, int L, int R, const int u) {
if (ir (L, R, l, r)) {
return w[u];
} else if (not otr (L, R, l, r)) {
int m = (L + R) >> 1;
pushdown (u);
return max (query (l, r, L, m, u * 2), query (l, r, m + 1, R, u * 2 + 1));
} else {
return 0;
}
}
void update (int l, int r, int L, int R, const int u, int x, bool type) {
if (ir (L, R, l, r)) {
maketag (u, x, type);
return;
} else if (not otr (L, R, l, r)) {
int m = (L + R) >> 1;
pushdown (u);
update (l, r, L, m, u * 2, x, type);
update (l, r, m + 1, R, u * 2 + 1, x, type);
pushup (u);
} else {
return;
}
}
int op, l, r, x;
signed main () {
ios::sync_with_stdio (false);
cin.tie (0);
cout.tie (0);
cin >> n >> q;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
build (1, 1, n);
while (q--) {
cin >> op;
if (op == 1) {
cin >> l >> r >> x;
update (l, r, 1, n, 1, x, 1);
} else if (op == 2) {
cin >> l >> r >> x;
update (l, r, 1, n, 1, x, 0);
} else {
cin >> l >> r;
cout << query (l, r, 1, n, 1) << '\n';
}
}
return 0;
}