#include <bits/stdc++.h>
template <typename T>
inline bool tensionv(T &a, const T &b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
inline unsigned int getuint() {
  char w = getchar();
  while (w < '0' || '9' < w) w = getchar();
  unsigned int ans = 0;
  for (; '0' <= w && w <= '9'; w = getchar()) ans = ans * 10 + w - '0';
  return ans;
}
inline unsigned long long getuint64() {
  char w = getchar();
  while (w < '0' || '9' < w) w = getchar();
  unsigned long long ans = 0;
  for (; '0' <= w && w <= '9'; w = getchar()) ans = ans * 10 + w - '0';
  return ans;
}
unsigned long long h;
int n, m, q;
const int MAXV = 20005, MAXN = 200005;
std::pair<unsigned long long, int> a[MAXN];
int flag[MAXN];
unsigned long long dist[MAXV];
void dijkstra(unsigned long long d) {
  static std::pair<unsigned long long, int> heap[MAXV * 20];
  static int heap_size;
  for (int i = 0; i < m; i++)
    if (dist[i] != 0x3f3f3f3f3f3f3f3fllu)
      heap[heap_size++] = std::make_pair(dist[i], i);
  for (std::make_heap(heap, heap + heap_size,
                      std::greater<std::pair<unsigned long long, int> >());
       heap_size;) {
    std::pair<unsigned long long, int> p = *heap;
    std::pop_heap(heap, heap + heap_size--,
                  std::greater<std::pair<unsigned long long, int> >());
    if (p.first != dist[p.second]) continue;
    int x = p.second, y = (x + d) % m;
    if (tensionv(dist[y], dist[x] + d))
      heap[heap_size++] = std::make_pair(dist[y], y),
      std::push_heap(heap, heap + heap_size,
                     std::greater<std::pair<unsigned long long, int> >());
  }
}
std::pair<int, int> heap[MAXN];
int heap_size;
inline bool cmp(const std::pair<int, int> &i, const std::pair<int, int> &j) {
  return i.first != j.first ? i.first < j.first : i.second > j.second;
}
int main() {
  h = getuint64(), n = getuint(), q = getuint(), m = getuint();
  memset(dist + 1, 0x3f, sizeof(unsigned long long) * (m - 1));
  for (int i = 1; i <= n; i++) {
    a[i].first = getuint64() - 1, a[i].second = getuint();
    if (a[i].first % m == 0) heap[heap_size++] = std::make_pair(a[i].second, i);
  }
  for (std::make_heap(heap, heap + heap_size, cmp); q--;) {
    int type = getuint();
    if (type == 1) {
      dijkstra(getuint64());
      heap_size = 0;
      for (int i = 1; i <= n; i++)
        if (!flag[i] && dist[a[i].first % m] <= a[i].first)
          heap[heap_size++] = std::make_pair(a[i].second, i);
      std::make_heap(heap, heap + heap_size, cmp);
    } else if (type == 2) {
      int x = getuint(), y = getuint();
      if (!y) continue;
      a[x].second -= y;
      if (!flag[x] && dist[a[x].first % m] <= a[x].first)
        heap[heap_size++] = std::make_pair(a[x].second, x),
        std::push_heap(heap, heap + heap_size, cmp);
    } else {
      while (heap_size && heap->first != a[heap->second].second)
        std::pop_heap(heap, heap + heap_size--, cmp);
      if (heap_size)
        printf("%d\n", heap->first),
            flag[heap->second] = 1,
            std::pop_heap(heap, heap + heap_size--, cmp);
      else
        puts("0");
    }
  }
  return 0;
}
