#include <bits/stdc++.h>
#include <climits>
#ifndef ONLINE_JUDGE
#include "debug.h"
#else
#define debug(...)
#endif
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
template <class T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
template <class T>
using ordered_multiset = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;
#define ll long long
#define ld long double
#define endl '\n'
const ld eps = 1e-12;
ll no_operation = LLONG_MAX;
ll x;
struct Node {
ll l = -1, r = -1;
ll sum = 0;
ll operation = no_operation;
bool type = false;
ll maxi = LLONG_MIN;
Node(ll val, ll idx) {
// debug(x);
l = idx, r = idx;
sum = val;
maxi = val - l * x;
}
Node() {
}
void apply(ll op) {
type = false;
operation = op;
sum = (r - l + 1) * op;
maxi = op - l * x;
}
void apply1(ll op) {
if (operation != no_operation) {
operation += op;
} else if (operation == no_operation) {
operation = op;
type = true;
}
sum += (r - l + 1) * op;
maxi += op;
}
};
struct Stree {
vector<Node> segtree;
vector<ll> arr;
void init(ll n, vector<ll> A) {
arr = A;
segtree.resize(4 * (n + 1));
}
Node merge(const Node &left, const Node &right) {
if (left.l == -1)return right;
if (right.l == -1)return left;
Node cur;
cur.l = left.l;
cur.r = right.r;
cur.maxi = max(left.maxi, right.maxi);
cur.sum = right.sum + left.sum;
return cur;
}
void propagate(ll tl, ll tr, ll node) {
if (tl >= tr)return;
if (segtree[node].operation != no_operation) {
ll op = segtree[node].operation;
if (!segtree[node].type) {
segtree[2 * node].apply(op);
segtree[2 * node + 1].apply(op);
} else {
segtree[2 * node].apply1(op);
segtree[2 * node + 1].apply1(op);
}
}
segtree[node].operation = no_operation;
}
void build(ll l, ll r, ll node) {
if (l > r) return;
if (l == r) {
segtree[node] = Node(arr[l], l);
return;
}
ll mid = (l + r) >> 1;
build(l, mid, 2 * node);
build(mid + 1, r, 2 * node + 1);
segtree[node] = merge(segtree[2 * node], segtree[2 * node + 1]);
}
Node query(ll l, ll r, ll tl, ll tr, ll node) {
propagate(tl, tr, node);
if (l > r || tl > tr || tl > r || tr < l) return Node();
if (tl >= l && tr <= r) {
return segtree[node];
}
ll mid = (tl + tr) >> 1;
return merge(query(l, r, tl, mid, 2 * node) ,
query(l, r, mid + 1, tr, 2 * node + 1));
}
ll Query(ll idx, ll val, ll tl, ll tr, ll node)
{
propagate(tl, tr, node);
if (tl > tr || segtree[node].maxi < val || tl >= idx)return -1;
if (tl == tr)return tl;
ll mid = (tl + tr) >> 1;
ll right = Query(idx, val, mid + 1, tr, 2 * node + 1);
if (right != -1)return right;
return Query(idx, val, tl, mid, 2 * node);
}
void update(ll l, ll r, bool type, ll value, ll tl, ll tr, ll node) {
propagate(tl, tr, node);
ll mid = (tl + tr) >> 1;
if (tl > tr || tr < l || tl > r || l > r) return;
if (tl >= l && tr <= r) {
// we apply update
if (!type)
segtree[node].apply(value);
else segtree[node].apply1(value);
return;
}
update(l, r, type, value, tl, mid, 2 * node);
update(l, r, type, value, mid + 1, tr, 2 * node + 1);
segtree[node] = merge(segtree[2 * node], segtree[2 * node + 1]);
}
void update(ll l, ll val, ll tl, ll tr, ll node) {
propagate(tl, tr, node);
ll mid = (tl + tr) >> 1;
if (tl > tr || tr < l || tl > l) return;
if (tl == l && tr == l) {
segtree[node] = Node(val, l);
return;
}
update(l, val, tl, mid, 2 * node);
update(l, val, mid + 1, tr, 2 * node + 1);
segtree[node] = merge(segtree[2 * node], segtree[2 * node + 1]);
}
};
void solve() {
ll n, q; cin >> n >> q >> x;
vector<ll> a(n + 1);
vector<ll> arr(n + 1, 0);
for (ll i = 1; i <= n; i++)cin >> a[i];
Stree just;
just.init(n + 1, a);
just.build(1, n, 1);
while (q--) {
ll type; cin >> type;
if (type == 1 || type == 2) {
ll l, r ; cin >> l >> r;
ll val ; cin >> val;
just.update(l, r, (type == 2), val, 1, n, 1);
} else {
ll i , k; cin >> i >> k;
ll cur = just.query(i, i, 1, n, 1).sum;
if (k < cur) {
cout << -1 << endl;
continue;
}
if (k == cur) {
cout << 0 << endl;
continue;
}
auto ck1 = [&](ll mid)->ll{
ll looking = mid - i * x ;
ll idx = just.Query(i, looking, 1, n, 1);
if (idx != -1) {
ll su = just.query(idx + 1, i, 1, n, 1).sum;
ll len = i - idx;
ll sum = (2 * mid + (len - 1) * (-x)) * len;
sum >>= 1;
return sum - su;
} return -1;
};
cout << ck1(k) << endl;
}
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
#ifndef ONLINE_JUDGE
freopen("F:\\cp_sublime\\input.txt", "r", stdin);
freopen("F:\\cp_sublime\\output.txt", "w", stdout);
freopen("F:\\cp_sublime\\debug.txt", "w", stderr);
#endif
int tt = 1;
cin >> tt;
while (tt--)
solve();
}