#include <bits/stdc++.h>
using namespace std;
const int inf = ~0U >> 1;
const long long INF = ~0ULL >> 1;
;
const double pi = acos(-1.0);
template <class T>
inline T sqr(T a) {
  return a * a;
}
template <class T>
inline void read(T &n) {
  char c;
  for (c = getchar(); !(c >= '0' && c <= '9'); c = getchar())
    ;
  n = c - '0';
  for (c = getchar(); c >= '0' && c <= '9'; c = getchar()) n = n * 10 + c - '0';
}
int Pow(int base, int n, int mo) {
  if (n == 0) return 1;
  if (n == 1) return base;
  int tmp = Pow(base, n >> 1, mo);
  tmp = (long long)tmp * tmp % mo;
  if (n & 1) tmp = (long long)tmp * base % mo;
  return tmp;
}
struct point {
  int x, y;
  point() {}
  point(int _x, int _y) : x(_x), y(_y) {}
};
const int maxn = 200000;
long long a[maxn], d[maxn], step[maxn], h;
int n, m, k, K, ty, c[maxn], vis[maxn];
struct cmp {
  bool operator()(const pair<int, long long> &a,
                  const pair<int, long long> &b) const {
    return (a.first > b.first) || (a.first == b.first && a.second < b.second);
  }
};
set<pair<int, long long>, cmp> heap;
priority_queue<pair<long long, int> > Heap;
map<long long, int> taken;
void shortest_path() {
  for (int i = (0); i <= (k - 1); ++i) d[i] = INF, vis[i] = 0;
  d[1] = 1;
  for (int i = (0); i <= (k - 1); ++i) Heap.push((make_pair(-d[i], i)));
  while (Heap.size()) {
    int u = Heap.top().second;
    Heap.pop();
    if (vis[u] || d[u] == INF) continue;
    vis[u] = 1;
    for (int i = (1); i <= (K); ++i) {
      int v = (d[u] + step[i]) % k;
      if (d[u] + step[i] < d[v]) {
        d[v] = d[u] + step[i];
        Heap.push((make_pair(-d[v], v)));
      }
    }
  }
  for (int i = (0); i <= (k - 1); ++i)
    if (d[i] == INF) d[i] = -1;
  heap.clear();
  for (int i = (1); i <= (n); ++i) {
    int g = a[i] % k;
    if (d[g] != -1 && a[i] >= d[g] && !taken[a[i]])
      heap.insert((make_pair(c[i], i)));
  }
}
int main() {
  memset(d, -1, sizeof(d));
  scanf("%lld%d%d%d", &h, &n, &m, &k);
  d[1] = 1;
  for (int i = (1); i <= (n); ++i) {
    scanf("%lld%d", &a[i], &c[i]);
    int g = a[i] % k;
    if (d[g] != -1 && a[i] >= d[g]) heap.insert((make_pair(c[i], i)));
  }
  while (m--) {
    scanf("%d", &ty);
    if (ty == 1) {
      long long x;
      scanf("%lld", &x);
      step[++K] = x;
      shortest_path();
    } else if (ty == 2) {
      int x, delta;
      scanf("%d%d", &x, &delta);
      assert(!taken[a[x]]);
      int g = a[x] % k;
      set<pair<int, long long>, cmp>::iterator itr =
          heap.find((make_pair(c[x], x)));
      if (d[g] != -1 && a[x] >= d[g]) {
        heap.erase(itr);
        c[x] -= delta;
        heap.insert((make_pair(c[x], x)));
      } else
        c[x] -= delta;
    } else if (ty == 3) {
      if (!heap.size()) {
        puts("0");
        continue;
      }
      pair<int, long long> ret = *heap.begin();
      heap.erase(heap.begin());
      taken[a[ret.second]] = 1;
      printf("%d\n", ret.first);
    }
  }
  return 0;
}
