#include <bits/stdc++.h>
using namespace std;
struct SegTree {
struct Node {
long long maxv, lazy;
};
int n;
vector<Node> st;
SegTree(int _n) : n(_n) {
st.assign(4 * n + 4, {0, 0});
}
void build(int p, int l, int r, const vector<long long>& a) {
if (l == r) {
st[p].maxv = a[l];
} else {
int m = (l + r) >> 1;
build(p << 1, l, m, a);
build(p << 1 | 1, m + 1, r, a);
st[p].maxv = max(st[p << 1].maxv, st[p << 1 | 1].maxv);
}
}
void apply(int p, long long v) {
st[p].maxv += v;
st[p].lazy += v;
}
void push(int p) {
if (st[p].lazy != 0) {
apply(p << 1, st[p].lazy);
apply(p << 1 | 1, st[p].lazy);
st[p].lazy = 0;
}
}
void update(int p, int l, int r, int i, int j, long long v) {
if (i > r || j < l) return;
if (i <= l && r <= j) {
apply(p, v);
return;
}
push(p);
int m = (l + r) >> 1;
update(p << 1, l, m, i, j, v);
update(p << 1 | 1, m + 1, r, i, j, v);
st[p].maxv = max(st[p << 1].maxv, st[p << 1 | 1].maxv);
}
long long query(int p, int l, int r, int i, int j) {
if (i > r || j < l) return LLONG_MIN;
if (i <= l && r <= j) {
return st[p].maxv;
}
push(p);
int m = (l + r) >> 1;
return max(
query(p << 1, l, m, i, j),
query(p << 1 | 1, m + 1, r, i, j)
);
}
// Helpers
void build(const vector<long long>& a) {
build(1, 1, n, a);
}
void update(int l, int r, long long v) {
update(1, 1, n, l, r, v);
}
long long query(int l, int r) {
return query(1, 1, n, l, r);
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) {
int N, Q;
cin >> N >> Q;
vector<long long> A(N + 1);
for (int i = 1; i <= N; ++i) {
cin >> A[i];
}
SegTree st(N);
st.build(A);
for (int q = 0; q < Q; ++q) {
int type, L, R;
cin >> type >> L >> R;
if (type == 1) {
long long V;
cin >> V;
st.update(L, R, V);
} else if (type == 2) {
cout << st.query(L, R) << '\n';
}
}
}
return 0;
}