#include <bits/stdc++.h>
using namespace std;
struct SegmentTree {
int n;
vector<long long> tree, lazy;
SegmentTree(int n) : n(n) {
tree.assign(4*n, 0);
lazy.assign(4*n, 0);
}
void build(vector<long long>& arr, int node, int l, int r) {
if (l == r) {
tree[node] = arr[l];
return;
}
int mid = (l + r) / 2;
build(arr, 2*node, l, mid);
build(arr, 2*node+1, mid+1, r);
tree[node] = max(tree[2*node], tree[2*node+1]);
}
void pushDown(int node, int l, int r) {
if (lazy[node] != 0) {
tree[node] += lazy[node];
if (l != r) {
lazy[2*node] += lazy[node];
lazy[2*node+1] += lazy[node];
}
lazy[node] = 0;
}
}
void update(int node, int l, int r, int ql, int qr, long long val) {
pushDown(node, l, r);
if (qr < l || ql > r) return;
if (ql <= l && r <= qr) {
lazy[node] += val;
pushDown(node, l, r);
return;
}
int mid = (l + r) / 2;
update(2*node, l, mid, ql, qr, val);
update(2*node+1, mid+1, r, ql, qr, val);
tree[node] = max(tree[2*node], tree[2*node+1]);
}
long long query(int node, int l, int r, int ql, int qr) {
pushDown(node, l, r);
if (qr < l || ql > r) return LLONG_MIN;
if (ql <= l && r <= qr) return tree[node];
int mid = (l + r) / 2;
return max(query(2*node, l, mid, ql, qr),
query(2*node+1, mid+1, r, ql, qr));
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T; cin >> T;
while (T--) {
int N; cin >> N;
vector<long long> arr(N+1);
for (int i = 1; i <= N; i++) cin >> arr[i];
SegmentTree seg(N);
seg.build(arr, 1, 1, N);
int Q; cin >> Q;
while (Q--) {
int type; cin >> type;
if (type == 1) {
int L, R; long long X;
cin >> L >> R >> X;
seg.update(1, 1, N, L, R, X);
} else {
int L, R;
cin >> L >> R;
cout << seg.query(1, 1, N, L, R) << "\n";
}
}
}
return 0;
}