#include <bits/stdc++.h>
using namespace std;
template <class T>
inline void umax(T &a, T b) {
  if (a < b) a = b;
}
template <class T>
inline void umin(T &a, T b) {
  if (a > b) a = b;
}
template <class T>
inline T abs(T a) {
  return a > 0 ? a : -a;
}
template <class T>
inline T gcd(T a, T b) {
  return __gcd(a, b);
}
template <class T>
inline T lcm(T a, T b) {
  return a / gcd(a, b) * b;
}
const int inf = 1e9 + 143;
const long long longinf = 1e18 + 143;
inline int read() {
  int x;
  scanf(" %d", &x);
  return x;
}
const int N = 1e5 + 100;
const int MAX = 1e4 + 100;
int n;
long long x[N];
int c[N];
set<pair<int, int> > reach;
bool taken[N];
int sz = 0;
long long a[N];
priority_queue<pair<long long, int> > q;
long long dist[MAX];
bool used[MAX];
void rebuild() {
  sort(a, a + sz);
  sz = unique(a, a + sz) - a;
  int mod = a[0];
  dist[0] = 0;
  used[0] = 0;
  for (int i = 1; i < mod; i++) {
    dist[i] = longinf;
    used[i] = 0;
  }
  q.push(make_pair(0ll, 0));
  while (!q.empty()) {
    int u = q.top().second;
    long long len = -q.top().first;
    q.pop();
    if (dist[u] < len) continue;
    for (int i = 1; i < sz; i++) {
      int v = (u + a[i]) % mod;
      long long c = a[i];
      if (dist[v] > dist[u] + c) {
        dist[v] = dist[u] + c;
        q.push(make_pair(-dist[v], v));
      }
    }
  }
  reach.clear();
  for (int i = 0; i < n; i++) {
    if (taken[i]) continue;
    if (dist[x[i] % mod] <= x[i]) {
      reach.insert(make_pair(-c[i], i));
    }
  }
}
int main() {
  long long h;
  cin >> h;
  n = read();
  int m = read();
  a[sz++] = read();
  for (int i = 0; i < n; i++) {
    scanf(" %I64d", x + i);
    --x[i];
    c[i] = read();
  }
  rebuild();
  while (m--) {
    int op = read();
    if (op == 1) {
      long long x;
      scanf(" %I64d", &x);
      a[sz++] = x;
      rebuild();
    } else if (op == 2) {
      int id = read() - 1;
      int y = read();
      if (reach.find(make_pair(-c[id], id)) != reach.end()) {
        reach.erase(make_pair(-c[id], id));
        c[id] -= y;
        reach.insert(make_pair(-c[id], id));
      } else {
        c[id] -= y;
      }
    } else if (op == 3) {
      if (!reach.size()) {
        puts("0");
      } else {
        printf("%d\n", -reach.begin()->first);
        taken[reach.begin()->second] = true;
        reach.erase(reach.begin());
      }
    }
  }
  return 0;
}
