#include <bits/stdc++.h>
using namespace std;
struct edge {
  long long x, c;
};
struct treasure {
  long long cell;
  long long c;
};
long long h, dist[10010];
long long n, k;
vector<edge> v[10100];
treasure a[100100];
set<pair<long long, long long> > s, sans;
bool mark[100100];
pair<long long, long long> findmin() {
  set<pair<long long, long long> >::iterator it = s.begin();
  pair<long long, long long> p = *it;
  s.erase(p);
  return p;
}
void sethams(long long x) {
  for (long long i = 0; i < v[x].size(); i++) {
    edge e = v[x][i];
    long long d = dist[x] + e.c;
    if (d >= h) continue;
    if (dist[e.x] == -1 || dist[e.x] > d) {
      if (dist[e.x] > d) s.erase(make_pair(dist[e.x], e.x));
      dist[e.x] = d;
      s.insert(make_pair(dist[e.x], e.x));
    }
  }
}
void dijkstra() {
  fill(dist, dist + k, -1);
  s.clear();
  dist[0] = 0;
  s.insert(make_pair(0, 0));
  while (!s.empty()) {
    pair<long long, long long> p = findmin();
    sethams(p.second);
  }
}
void setset() {
  sans.clear();
  for (long long i = 0; i < n; i++) {
    if (mark[i]) continue;
    treasure t = a[i];
    if (dist[(t.cell % k)] <= t.cell && dist[(t.cell % k)] != -1 && t.c > 0)
      sans.insert(make_pair(-t.c, i));
  }
}
void query1(long long o) {
  for (long long i = 0; i < k; i++) {
    edge e;
    e.x = (i + o) % k;
    e.c = o;
    v[i].push_back(e);
  }
  dijkstra();
  setset();
}
int main() {
  long long m;
  cin >> h >> n >> m >> k;
  for (long long i = 0; i < n; i++) cin >> a[i].cell >> a[i].c, a[i].cell--;
  query1(k);
  for (long long i = 0; i < m; i++) {
    long long t;
    cin >> t;
    if (t == 1) {
      long long o;
      cin >> o;
      query1(o);
    }
    if (t == 2) {
      long long x, c;
      cin >> x >> c;
      x--;
      bool ch = sans.find(make_pair(-a[x].c, x)) != sans.end();
      if (ch) {
        sans.erase(make_pair(-a[x].c, x));
        sans.insert(make_pair(-a[x].c + c, x));
      }
      a[x].c -= c;
    }
    if (t == 3) {
      if (sans.empty())
        cout << 0 << endl;
      else {
        set<pair<long long, long long> >::iterator it = sans.begin();
        pair<long long, long long> p = *it;
        sans.erase(p);
        mark[p.second] = 1;
        cout << -p.first << endl;
      }
    }
  }
  return 0;
}
