#include <bits/stdc++.h>
using namespace std;
const long long inf = ((long long)1) << 60;
const double dinf = 1e50;
const int INF = 1000000000;
const int N = 100005;
struct node {
  int L, R, mid, Max;
};
node a[N << 2];
int b[N], c[N];
vector<int> V[N];
int n, m, K;
long long h, pos[N], p[N], cnt, d[N];
void Add(long long t) {
  p[cnt++] = t;
  memset(d, -1, sizeof(d));
  int h[N] = {0}, i, j, u, v;
  long long x, y;
  queue<int> Q;
  Q.push(1);
  d[1] = 0;
  while (!Q.empty()) {
    u = Q.front();
    Q.pop();
    h[u] = 0;
    for (i = 0; i < cnt; i++) {
      x = (u + p[i]) / K;
      y = (u + p[i]) % K;
      if (d[y] == -1 || d[y] > d[u] + x) {
        d[y] = d[u] + x;
        if (!h[y]) Q.push(y);
      }
    }
  }
  memset(b, 0, sizeof(b));
  for (i = 0; i < K; i++)
    if (d[i] != -1)
      for (j = 0; j < V[i].size(); j++) {
        u = V[i][j];
        if (pos[u] >= d[i] * K + i) b[u] = 1;
      }
}
void pushUp(int t) {
  a[t].Max = ((a[t * 2].Max) > (a[t * 2 + 1].Max) ? (a[t * 2].Max)
                                                  : (a[t * 2 + 1].Max));
}
void build(int t, int L, int R) {
  a[t].L = L;
  a[t].R = R;
  a[t].mid = (L + R) >> 1;
  if (L == R) {
    if (!b[L])
      a[t].Max = -1;
    else
      a[t].Max = c[L];
    return;
  }
  build(t * 2, L, a[t].mid);
  build(t * 2 + 1, a[t].mid + 1, R);
  pushUp(t);
}
void update(int t, int x, int y) {
  if (a[t].L == a[t].R) {
    a[t].Max -= y;
    c[x] -= y;
    return;
  }
  if (x <= a[t].mid)
    update(t * 2, x, y);
  else
    update(t * 2 + 1, x, y);
  pushUp(t);
}
void modify(int t, int x) {
  if (a[t].L == a[t].R) {
    a[t].Max = 0;
    c[a[t].L] = 0;
    return;
  }
  if (a[t * 2].Max == x)
    modify(t * 2, x);
  else
    modify(t * 2 + 1, x);
  pushUp(t);
}
int main() {
  cin >> h >> n >> m >> K;
  int i;
  for (i = 1; i <= n; i++) {
    cin >> pos[i] >> c[i];
    V[pos[i] % K].push_back(i);
    if (pos[i] % K == 1) b[i] = 1;
  }
  build(1, 1, n);
  int op, x, y;
  long long A;
  while (m--) {
    cin >> op;
    if (op == 1) {
      cin >> A;
      Add(A);
      build(1, 1, n);
    } else if (op == 2) {
      cin >> x >> y;
      update(1, x, y);
    } else {
      if (a[1].Max <= 0)
        puts("0");
      else {
        cout << a[1].Max << endl;
        modify(1, a[1].Max);
      }
    }
  }
}
