#include <bits/stdc++.h>
using namespace std;
const int M = 100000 + 5;
map<long long int, int> mp;
queue<int> Q;
int vis[M];
long long int dk[M];
vector<long long int> step;
long long int a[M];
int rch[M];
struct TREE {
  int lc;
  int rc;
  long long int l;
  long long int r;
  long long int idx;
  long long int val;
} tree[20 * M];
int tot = 1;
void update(long long int l, long long int r, int node, long long int val,
            long long int idx) {
  if (l == r) {
    tree[node].val += val;
    tree[node].l = l;
    tree[node].r = r;
    tree[node].idx = idx;
    tree[node].lc = node;
    tree[node].rc = node;
    return;
  }
  long long int m = (l + r) / 2;
  if (tree[node].lc == 0) {
    tot++;
    tree[node].lc = tot;
  }
  if (tree[node].rc == 0) {
    tot++;
    tree[node].rc = tot;
  }
  if (idx <= m) {
    update(l, m, tree[node].lc, val, idx);
  } else {
    update(m + 1, r, tree[node].rc, val, idx);
  }
  int lc = tree[node].lc;
  int rc = tree[node].rc;
  if (tree[lc].val < tree[rc].val) {
    tree[node].idx = tree[rc].idx;
    tree[node].val = tree[rc].val;
  } else {
    tree[node].idx = tree[lc].idx;
    tree[node].val = tree[lc].val;
  }
  return;
}
int main() {
  time_t t_start, t_end;
  t_start = clock();
  long long int h;
  cin >> h;
  int n, m, k;
  cin >> n >> m >> k;
  for (int i = 0; i < n; i++) {
    long long int ai;
    int ci;
    cin >> ai >> ci;
    a[i + 1] = ai;
    mp[ai] = ci;
    if (ai % k == 1) {
      rch[i + 1] = 1;
      update(1, M, 1, ci, i + 1);
    }
  }
  step.push_back(k);
  for (int q = 0; q < m; q++) {
    int ty;
    cin >> ty;
    if (ty == 1) {
      long long int x;
      cin >> x;
      step.push_back(x);
      for (int i = 0; i < M; i++) {
        vis[i] = 0;
        dk[i] = -1;
      }
      Q.push(1);
      dk[1] = 0;
      while (!Q.empty()) {
        int u = Q.front();
        vis[u] = 0;
        Q.pop();
        for (int i = 0; i < step.size(); i++) {
          long long int dx = step[i];
          int nxtu = (u + dx) % k;
          long long int nxty = (u + dk[u] * k + dx) / k;
          if (dk[nxtu] == -1 || dk[nxtu] > nxty) {
            dk[nxtu] = nxty;
            if (vis[nxtu] == 0) {
              Q.push(nxtu);
              vis[nxtu] = 1;
            }
          }
        }
      }
      for (int i = 1; i <= n; i++) {
        long long int ai = a[i];
        int u = ai % k;
        if (dk[u] != -1) {
          long long int yy = dk[u] * k + u;
          if (ai >= yy && rch[i] == 0) {
            rch[i] = 1;
            update(1, M, 1, mp[ai], i);
          }
        }
      }
    }
    if (ty == 2) {
      int x;
      long long int y;
      cin >> x >> y;
      long long int ai = a[x];
      mp[ai] = mp[ai] - y;
      if (rch[x] == 1) {
        update(1, M, 1, -y, x);
      }
    }
    if (ty == 3) {
      long long int res = tree[1].val;
      cout << res << endl;
      update(1, M, 1, -res, tree[1].idx);
    }
  }
  t_end = clock();
  return 0;
}
