#include <iostream>
#include <vector>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#define int long long
#define inf 2e18
using namespace std;
const int N = 1e6 + 10;
typedef long long ll;
inline char gc()
{
return getchar();
}
inline void pc(char c)
{
putchar(c);
}
ll readin()
{
ll x = 0;
int opt = 1;
char c = gc();
while (c < '0' || c > '9')
{
if (c == '-')
opt = -1;
c = gc();
}
while (c >= '0' && c <= '9')
{
x = x * 10 + (c - '0');
c = gc();
}
return opt * x;
}
inline ll ls(ll x)
{
return x << 1;
}
inline ll rs(ll x)
{
return x << 1 | 1;
}
ll a[N << 2];
ll mx[N << 2];
ll tag[N << 2];
ll tot[N << 2];
void push_up(int x)
{
mx[x] = max(mx[ls(x)], mx[rs(x)]);
}
void build(int x, int l, int r)
{
if (l == r)
{
tot[x] = -inf;
mx[x] = a[l];
return ;
}
int mid = (l + r) >> 1;
build(ls(x), l, mid);
build(rs(x), mid + 1, r);
push_up(x);
}
void add(int x, int l, int r, ll k)
{
mx[x] += k;
tag[x] += k;
}
void gai(int x, int l, int r, ll k)
{
mx[x] = k;
tot[x] = k;
tag[x] = 0;
}
void push_down_tot(int x, int l, int r)
{
if (tot[x] != -inf)
{
int mid = (l + r) >> 1;
gai(ls(x), l, mid, tot[x]);
gai(rs(x), mid + 1, r, tot[x]);
tot[x] = -inf;
}
}
void push_down_tag(int x, int l, int r)
{
if (tag[x] != 0)
{
push_down_tot(x, l, r);
int mid = (l + r) >> 1;
add(ls(x), l, mid, tag[x]);
add(rs(x), mid + 1, r, tag[x]);
tag[x] = 0;
}
}
void add_lr(int x, int l, int r, int L, int R, ll k)
{
if (L <= l && r <= R)
{
push_down_tot(x, l, r);
add(x, l, r, k);
return ;
}
int mid = (l + r) >> 1;
push_down_tot(x, l, r);
push_down_tag(x, l, r);
if (L <= mid)
add_lr(ls(x), l, mid, L, R, k);
if (R > mid)
add_lr(rs(x), mid + 1, r, L, R, k);
push_up(x);
}
void gai_lr(int x, int l, int r, int L, int R, ll k)
{
if (L <= r && r <= R)
{
gai(x, l, r, k);
return ;
}
int mid = (l + r) >> 1;
push_down_tot(x, l, r);
push_down_tag(x, l, r);
if (L <= mid)
gai_lr(ls(x), l, mid, L, R, k);
if (R > mid)
gai_lr(rs(x), mid + 1, r, L, R, k);
push_up(x);
}
ll query(int x, int l, int r, int L, int R)
{
if (L <= l && r <= R)
return mx[x];
int mid = (l + r) >> 1;
push_down_tot(x, l, r);
push_down_tag(x, l, r);
ll ret = -2e18;
if (L <= mid)
ret = max(ret, query(ls(x), l, mid, L, R));
if (R > mid)
ret = max(ret, query(rs(x), mid + 1, r, L, R));
return ret;
}
signed main()
{
int n, q;
n = readin();
q = readin();
for (int i = 1; i <= n; ++i)
a[i] = readin();
build(1, 1, n);
for (int i = 1; i <= 4 * n; ++i)
tot[i] = -inf;
while (q--)
{
int opt, l, r;
opt = readin();
l = readin();
r = readin();
if (opt == 1)
{
ll x;
x = readin();
gai_lr(1, 1, n, l, r, x);
}
if (opt == 2)
{
ll x;
x = readin();
add_lr(1, 1, n, l, r, x);
}
if (opt == 3)
{
cout << query(1, 1, n, l, r);
pc('\n');
}
}
return 0;
}