#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <string>
#define maxn 1000010
using namespace std;
typedef long long ll;
#define inf -100000000
struct node {
int l;
int r;
ll val;
ll add = 0;
ll add2 = inf;
ll ma = 0;
} a[maxn];
int num[maxn];
void build(int p, int l, int r) {
a[p].l = l;
a[p].r = r;
if (l == r) {
a[p].val = num[l];
return;
}
int mid = (l + r) / 2;
build(p * 2, l, mid);
build(p * 2 + 1, mid + 1, r);
a[p].val = a[p * 2].val + a[p * 2 + 1].val;
a[p].ma = max(a[p * 2].val, a[p * 2 + 1].val);
return;
}
void spread(int p) {
if (a[p].add2 != inf) {
a[p].add2 += a[p].add;
a[p * 2].val = (a[p * 2].r - a[p * 2 ].l + 1) * a[p].add2;
a[p * 2 + 1].val = (a[p * 2 + 1].r - a[p * 2 + 1].l + 1) * a[p].add2;
a[p * 2].add2 = a[p].add2;
a[p * 2].add = 0;
a[p * 2 + 1].add = 0;
a[p].add = 0;
a[p].add2 = inf;
} else {
a[p * 2].val += (a[p * 2].r - a[p * 2 ].l + 1) * a[p].add;
a[p * 2 + 1].val += (a[p * 2 + 1].r - a[p * 2 + 1].l + 1) * a[p].add;
a[p * 2].add += a[p].add;
a[p * 2 + 1].add += a[p].add;
a[p].add = 0;
}
}
void change1(int p, int l, int r, int z) {
if (l <= a[p].l && r >= a[p].r) {
a[p].add += z;
a[p].val += (ll)z * (a[p].r - a[p].l + 1);
a[p].ma = max(a[p * 2].val, a[p * 2 + 1].val);
return;
}
spread(p);
int mid = (a[p].l + a[p].r) / 2;
if (l <= mid) {
change1(p * 2, l, r, z);
}
if (r > mid) {
change1(p * 2 + 1, l, r, z);
}
a[p].val = a[p * 2].val + a[p * 2 + 1].val;
a[p].ma = max(a[p * 2].val, a[p * 2 + 1].val);
}
void change2(int p, int l, int r, int z) {
if (l <= a[p].l && r >= a[p].r) {
a[p].add2 = z;
a[p].val = (ll)(a[p].r - a[p].l + 1) * z;
a[p].ma = max(a[p * 2].val, a[p * 2 + 1].val);
return;
}
spread(p);
int mid = (a[p].l + a[p].r) / 2;
if (l <= mid) {
change2(p * 2, l, r, z);
}
if (r > mid) {
change2(p * 2 + 1, l, r, z);
}
a[p].val = a[p * 2].val + a[p * 2 + 1].val;
a[p].ma = max(a[p * 2].val, a[p * 2 + 1].val);
}
ll ask(int p, int l, int r) {
if (l <= a[p].l && r >= a[p].r) {
return a[p].ma;
}
spread(p);
ll ans1, ans2;
int mid = (a[p].l + a[p].r) / 2;
if (l <= mid) {
ans1 = ask(p * 2, l, r);
}
if (r > mid) {
ans2 = ask(p * 2 + 1, l, r);
}
return max(ans1, ans2);
}
int n, q;
int main() {
cin >> n >> q;
for (int i = 1; i <= n; i++) {
cin >> num[i];
}
build(1, 1, n);
int op, l, r, x;
for (int i = 1; i <= q; i++) {
cin >> op;
switch (op) {
case 1: {
cin >> l >> r >> x;
change2(1, l, r, x);
break;
}
case 2: {
cin >> l >> r >> x;
change1(1, l, r, x);
break;
}
case 3: {
cin >> l >> r;
cout << ask(1, l, r) << endl;
break;
}
}
}
return 0;
}