#include <bits/stdc++.h>
using namespace std;
const int N = 100005, MXK = 10004;
int n, q, k, M[N];
long long h, A[N], C[N], D[MXK];
vector<long long> Moves;
set<pair<long long, int> > ST;
inline void Build() {
  priority_queue<pair<long long, int> > Pq;
  memset(D, 63, sizeof(D));
  D[1 % k] = 1;
  Pq.push({-1, 1 % k});
  while (Pq.size()) {
    int v = Pq.top().second;
    int d = -Pq.top().first;
    Pq.pop();
    if (d > D[v]) continue;
    for (long long X : Moves) {
      int u = (v + X) % k;
      if (D[u] > D[v] + X) D[u] = D[v] + X, Pq.push({-D[u], u});
    }
  }
  for (int i = 1; i <= n; i++)
    if (!M[i] && D[A[i] % k] <= A[i]) ST.insert({-C[i], i});
}
int main() {
  scanf("%lld%d%d%d", &h, &n, &q, &k);
  for (int i = 1; i <= n; i++) scanf("%lld%lld", &A[i], &C[i]);
  Build();
  for (; q; q--) {
    int tp, id;
    long long X;
    scanf("%d", &tp);
    if (tp == 3) {
      if (!ST.size())
        printf("0\n");
      else {
        printf("%lld\n", -ST.begin()->first);
        M[ST.begin()->second] = 1;
        ST.erase(ST.begin());
      }
    } else if (tp == 2) {
      scanf("%d%lld", &id, &X);
      if (D[A[id] % k] <= A[id]) ST.erase({-C[id], id});
      C[id] -= X;
      if (D[A[id] % k] <= A[id]) ST.insert({-C[id], id});
    } else {
      scanf("%lld", &X);
      Moves.push_back(X);
      Build();
    }
  }
  return 0;
}
