#include <bits/stdc++.h>
using namespace std;
const int Maxn = 100005, Maxk = 10005;
const long long inf = 1999999999999999999LL + 208;
int n, m, k;
long long h, f[Maxk];
bool flag[Maxn];
template <class T>
void read(T &v) {
  char ch;
  while (!isdigit(ch = getchar()))
    ;
  v = ch - 48;
  while (isdigit(ch = getchar())) v = v * 10 + ch - 48;
}
struct Treasure {
  long long pos;
  int val;
} a[Maxn];
struct info {
  long long val;
  int i;
  info(long long val, int i) : val(val), i(i) {}
  bool operator<(const info &rhs) const {
    return val < rhs.val || (val == rhs.val && i > rhs.i);
  }
  bool operator>(const info &rhs) const { return val > rhs.val; }
};
priority_queue<info> H;
priority_queue<info, vector<info>, greater<info> > Q;
void predeal() {
  for (int i = 1; i <= n; i++)
    if (!flag[i] && a[i].val > 0 && a[i].pos >= f[a[i].pos % k])
      flag[i] = 1, H.push(info(a[i].val, i));
}
void expand() {
  long long e;
  read(e);
  for (int i = 0; i < k; i++)
    if (f[i] < inf) Q.push(info(f[i], i));
  while (!Q.empty()) {
    info x = Q.top();
    Q.pop();
    int t = (x.i + e) % k;
    if (x.val + e <= h && f[t] > x.val + e) Q.push(info(f[t] = x.val + e, t));
    while (!Q.empty() && Q.top().val != f[Q.top().i]) Q.pop();
  }
  predeal();
}
int main() {
  read(h);
  read(n);
  read(m);
  read(k);
  for (int i = 1; i <= n; i++) read(a[i].pos), read(a[i].val);
  for (int i = 0; i < k; i++) f[i] = inf;
  f[1] = 1;
  predeal();
  for (int i = 1, opx, x, y; i <= m; i++) {
    read(opx);
    if (opx == 1) expand();
    if (opx == 2) {
      read(x);
      read(y);
      a[x].val -= y;
      if (a[x].pos >= f[a[x].pos % k]) H.push(info(a[x].val, x));
    }
    if (opx == 3) {
      while (!H.empty() && H.top().val != a[H.top().i].val) H.pop();
      if (H.empty())
        puts("0");
      else {
        printf("%d\n", a[H.top().i].val);
        a[H.top().i].val = 0;
      }
    }
  }
  return 0;
}
