#include <bits/stdc++.h>
using namespace std;
set<pair<int, int> > treasure;
set<pair<int, int> > availableTreasure;
long long moves[22];
long long minStep[11111];
long long treasurePos[111111];
int updateAvailable(int mvcnt) {
  memset(minStep, 0x3F, sizeof(minStep));
  int minMove = *min_element(moves, moves + mvcnt);
  set<pair<long long, int> > q;
  minStep[0] = 0;
  q.insert(pair<long long, int>(0, 0));
  while (!q.empty()) {
    int x = q.begin()->second;
    q.erase(q.begin());
    long long xdis = minStep[x];
    for (int i = 0; i < mvcnt; i++) {
      int to = (x + moves[i]) % minMove;
      long long w = (x + moves[i]) / minMove;
      if (xdis + w < minStep[to]) {
        q.erase(pair<long long, int>(minStep[to], to));
        minStep[to] = xdis + w;
        q.insert(pair<long long, int>(minStep[to], to));
      }
    }
  }
  for (set<pair<int, int> >::iterator it = treasure.begin();
       it != treasure.end(); ++it) {
    int from = treasurePos[it->first] % minMove;
    if (minStep[from] > 0x3F00000000000000LL ||
        (long long)minStep[from] * minMove + from > treasurePos[it->first])
      continue;
    availableTreasure.insert(pair<int, int>(-it->second, it->first));
  }
  return 0;
}
int main(void) {
  long long H = 0;
  int N = 0;
  int M = 0;
  int k = 0;
  scanf("%I64d %d %d %d", &H, &N, &M, &k);
  int mvcnt = 0;
  moves[mvcnt++] = k;
  for (int i = 0; i < N; i++) {
    long long x = 0;
    int c = 0;
    scanf("%I64d %d", &x, &c);
    x--;
    treasurePos[i] = x;
    treasure.insert(pair<int, int>(i, c));
  }
  updateAvailable(mvcnt);
  for (int i = 0; i < M; i++) {
    int op = 0;
    scanf("%d", &op);
    if (op == 1) {
      long long nmv = 0;
      scanf("%I64d", &nmv);
      moves[mvcnt++] = nmv;
      updateAvailable(mvcnt);
    } else if (op == 2) {
      int x = 0;
      int nv = 0;
      scanf("%d %d", &x, &nv);
      x--;
      long long pos = treasurePos[x];
      set<pair<int, int> >::iterator it =
          treasure.lower_bound(pair<int, int>(x, -1));
      int ov = it->second;
      nv = ov - nv;
      treasure.erase(it);
      treasure.insert(pair<int, int>(x, nv));
      set<pair<int, int> >::iterator it2 =
          availableTreasure.find(pair<int, int>(-ov, x));
      if (it2 != availableTreasure.end()) {
        availableTreasure.erase(it2);
        availableTreasure.insert(pair<int, int>(-nv, x));
      }
    } else if (op == 3) {
      if (availableTreasure.empty())
        puts("0");
      else {
        set<pair<int, int> >::iterator ts = availableTreasure.begin();
        printf("%d\n", -ts->first);
        treasure.erase(pair<int, int>(ts->second, -ts->first));
        availableTreasure.erase(ts);
      }
    }
  }
  while (getchar() != EOF)
    ;
  return 0;
}
