#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
const long double eps = 1e-7;
const int inf = 1000000010;
const long long INF = 10000000000000010LL;
const int mod = 1000000007;
const int MAXN = 10010;
long long n, m, k, u, v, x, y, t, h, c, typ;
long long dist[MAXN];
bool mark[MAXN];
vector<pair<long long, long long>> G[MAXN];
priority_queue<pair<long long, long long>, vector<pair<long long, long long>>,
               greater<pair<long long, long long>>>
    pq;
void djkasra() {
  for (int i = 0; i < k; i++) pq.push({dist[i], i});
  while (!pq.empty()) {
    long long v = pq.top().second;
    pq.pop();
    for (pair<long long, long long> p : G[v]) {
      long long u = p.first, w = p.second;
      if (dist[v] + w < dist[u]) pq.push({dist[u] = dist[v] + w, u});
    }
  }
}
long long A[MAXN * 10];
long long C[MAXN * 10];
bool rem[MAXN * 10];
bool ok[MAXN * 10];
set<pair<long long, long long>> st;
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  memset(dist, 63, sizeof(dist));
  cin >> h >> n >> m >> k;
  for (int i = 1; i <= n; i++) {
    cin >> A[i] >> C[i];
    if (A[i] % k == 1) {
      ok[i] = 1;
      st.insert({-C[i], i});
    }
  }
  dist[1] = 0;
  while (m--) {
    cin >> typ;
    if (typ == 3) {
      t++;
      if (st.empty()) {
        cout << "0\n";
        continue;
      }
      long long tmp = (*st.begin()).second;
      st.erase(st.begin());
      rem[tmp] = 1;
      cout << C[tmp] << '\n';
      C[tmp] = 0;
    } else if (typ == 1) {
      cin >> x;
      for (int i = 0; i < k; i++) G[i].push_back({(i + x) % k, x});
      memset(mark, 0, sizeof(mark));
      djkasra();
      for (int i = 1; i <= n; i++) {
        if (ok[i]) continue;
        if (A[i] >= dist[A[i] % k]) {
          ok[i] = 1;
          st.insert({-C[i], i});
        }
      }
    } else {
      cin >> x >> y;
      if (st.count({-C[x], x})) {
        st.erase({-C[x], x});
        st.insert({-C[x] + y, x});
      }
      C[x] -= y;
    }
  }
  return 0;
}
