/// Md Abdur Rahman Salman ///
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
#define ll long long
#define bug(x) cout << #x << ": " << x << endl
const ll INF = -1e18;
int n;
vector<ll> a, tree, lazy;
void push(int node, int start, int end)
{
if(lazy[node] != 0)
{
tree[node] += lazy[node];
if(start != end)
{
lazy[2 * node] += lazy[node];
lazy[2 * node + 1] += lazy[node];
}
lazy[node] = 0;
}
}
void build(int node, int start, int end)
{
if(start == end)
{
tree[node] = a[start];
return;
}
int mid = start + (end - start) / 2;
build(2 * node, start, mid);
build(2 * node + 1, mid + 1, end);
tree[node] = max(tree[2 * node], tree[2 * node + 1]);
}
void updateRange(int node, int start, int end, int l, int r, int x)
{
push(node, start, end);
if(start > end || start > r || end < l) return;
if(l <= start && end <= r)
{
lazy[node] += x;
push(node, start, end);
return;
}
int mid = start + (end - start) / 2;
updateRange(2 * node, start, mid, l, r, x);
updateRange(2 * node + 1, mid + 1, end, l, r, x);
tree[node] = max(tree[2 * node], tree[2 * node + 1]);
}
ll queryRange(int node, int start, int end, int l, int r)
{
if(start > end || start > r || end < l) return INF;
push(node, start, end);
if(l <= start && end <= r) return tree[node];
int mid = start + (end - start) / 2;
ll p1 = queryRange(2 * node, start, mid, l, r);
ll p2 = queryRange(2 * node + 1, mid + 1, end, l, r);
return max(p1, p2);
}
int32_t main()
{
ios_base::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int t; cin >> t;
while(t--)
{
cin >> n;
a.resize(n + 1);
for(int i = 1; i <= n; i++) cin >> a[i];
tree.assign(4 * n + 4, 0);
lazy.assign(4 * n + 4, 0);
build(1, 1, n);
int q; cin >> q;
while(q--)
{
int val; cin >> val;
if(val == 1)
{
int l, r, x;
cin >> l >> r >> x;
updateRange(1, 1, n, l, r, x);
}
else
{
int l, r; cin >> l >> r;
cout << queryRange(1, 1, n, l, r) << endl;
}
}
}
return 0;
}