#include <bits/stdc++.h>
using namespace std;
int k;
vector<long long> earliest;
bool canReach(long long pos) { return earliest[pos % k] <= pos / k; }
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  long long h;
  int n, m;
  cin >> h >> n >> m >> k;
  earliest.resize(k, 1000000000000000001LL);
  earliest[0] = 0;
  vector<long long> a(n);
  vector<int> c(n);
  priority_queue<pair<int, int> > front;
  for (int i = 0; i < n; i++) {
    cin >> a[i];
    a[i]--;
    cin >> c[i];
    if (canReach(a[i])) front.push(make_pair(c[i], -i));
  }
  for (int query = 0; query < m; query++) {
    int op;
    cin >> op;
    if (op == 1) {
      long long x;
      cin >> x;
      priority_queue<pair<long long, int>, vector<pair<long long, int> >,
                     greater<pair<long long, int> > >
          toMod;
      for (int i = 0; i < k; i++)
        toMod.push(make_pair(earliest[i] + (i + x) / k, (i + x) % k));
      while (toMod.size() > 0) {
        auto cur = toMod.top();
        toMod.pop();
        if (earliest[cur.second] <= cur.first) continue;
        earliest[cur.second] = cur.first;
        toMod.push(
            make_pair(cur.first + (cur.second + x) / k, (cur.second + x) % k));
      }
      front = priority_queue<pair<int, int> >();
      for (int i = 0; i < n; i++)
        if (canReach(a[i])) front.push(make_pair(c[i], -i));
    }
    if (op == 2) {
      int x, y;
      cin >> x >> y;
      x--;
      c[x] -= y;
    }
    if (op == 3) {
      while (front.size() > 0 &&
             (front.top().first != c[-front.top().second])) {
        pair<int, int> toAdd =
            make_pair(c[-front.top().second], front.top().second);
        front.pop();
        front.push(toAdd);
      }
      if (front.size() == 0)
        cout << "0\n";
      else {
        c[-front.top().second] = 0;
        cout << front.top().first << '\n';
      }
    }
  }
  return 0;
}
