#include <bits/stdc++.h>
using namespace std;
int bitct(long long r) { return r == 0 ? 0 : (bitct(r >> 1) + (r & 1)); }
long long gcd(long long x, long long y) { return x ? gcd(y % x, x) : y; }
template <typename T>
ostream& operator<<(ostream& o, vector<T> v) {
  o << "{";
  int i = 0, s = v.size();
  for (; i + 1 < s; i++) o << v[i] << ", ";
  if (s) o << v[i];
  o << "}";
  return o;
}
long long choose(long long n, long long q) {
  if (n == 0 || q == 0) return 1;
  if (q == 1)
    return n;
  else
    return (choose(n, q - 1) * (n - q + 1) / q);
}
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
vector<long long> ta, tc;
set<pair<int, int>> reachable;
vector<long long> moves;
int k;
long long h;
void make_reach() {
  reachable.clear();
  vector<long long> r(k, -1);
  r[0] = 0;
  priority_queue<long long, vector<long long>, greater<long long>> Q;
  Q.push(0);
  while (Q.size()) {
    long long me = Q.top();
    Q.pop();
    for (long long i : moves) {
      long long nm = (i + me) % k;
      long long nv = i + r[me];
      if (nv > h) continue;
      if (-1 == r[nm % k] || nv < r[nm % k]) {
        r[nm % k] = nv;
        Q.push(nm % k);
      }
    }
  }
  for (int i = 0; i < ta.size(); i++)
    if (r[ta[i] % k] != -1 && r[ta[i] % k] <= ta[i])
      if (tc[i]) {
        reachable.insert(make_pair(tc[i], -i));
      }
}
int main() {
  int n, m;
  cin >> h >> n >> m >> k;
  for (int i = 0; i < n; i++) {
    long long a, c;
    cin >> a >> c;
    ta.push_back(a - 1);
    tc.push_back(c);
  }
  make_reach();
  for (int xx = 0; xx < m; xx++) {
    int typ = 0;
    cin >> typ;
    if (typ == 1) {
      long long x;
      cin >> x;
      moves.push_back(x);
      make_reach();
    } else if (typ == 2) {
      int x, y;
      cin >> x >> y;
      x--;
      int has = (reachable.end() != reachable.find(make_pair(tc[x], -x)));
      if (has) reachable.erase(make_pair(tc[x], -x));
      tc[x] -= y;
      if (has && tc[x] != 0) reachable.insert(make_pair(tc[x], -x));
    } else {
      if (reachable.size()) {
        cout << reachable.rbegin()->first << endl;
        int z = -reachable.rbegin()->second;
        tc[z] = 0;
        reachable.erase(*reachable.rbegin());
      } else
        cout << 0 << endl;
    }
  }
}
