#include <bits/stdc++.h>
using namespace std;
const long long MAXn = 1e5 + 10, SQ = 400, MAXq1 = 20 + 4, MAXk = 1e4 + 10,
                INF = 1e18;
pair<long long, int> ar[MAXn];
vector<pair<int, int> > v;
set<pair<int, int> > st;
long long n, m, h, q1, k, can[MAXk];
bool flag[MAXn];
bool cmp(pair<int, int> p1, pair<int, int> p2) {
  if (p1.first != p2.first) return p1.first < p2.first;
  return p2.second < p1.second;
}
void relax(int i, long long en) {
  for (; i < en; i += SQ) {
    int en2 = min(i + SQ, en);
    sort(v.begin() + i, v.begin() + en2, cmp);
  }
}
void update() {
  int st1 = v.size();
  for (int i = 0; i < n; i++)
    if (!flag[i])
      if (can[ar[i].first % k] <= ar[i].first) {
        flag[i] = true;
        st.insert(pair<int, int>(i, (int)v.size() / SQ));
        v.push_back(pair<int, int>(ar[i].second, i));
      }
  relax(0, (int)v.size());
}
void query1(long long a) {
  priority_queue<pair<long long, int> > q;
  for (int i = 0; i < k; i++) q.push(pair<long long, int>(-can[i], i));
  for (int i = 0; i < MAXk; i++) can[i] = INF;
  while (true) {
    if (q.empty()) break;
    pair<long long, int> hp = q.top();
    q.pop();
    while (can[hp.second] != INF) {
      if (q.empty()) break;
      hp = q.top();
      q.pop();
    }
    if (q.empty()) break;
    can[hp.second] = -hp.first;
    if (-hp.first + a < INF) {
      q.push(pair<long long, int>(hp.first - a, (hp.second + a) % k));
    }
  }
  update();
}
void query2(int x, int y) {
  if (flag[x]) {
    int hp = (*st.lower_bound(pair<int, int>(x, 0))).second;
    int st1 = hp * SQ, en = min(st1 + SQ, (long long)v.size());
    for (int i = st1; i < en; i++)
      if (v[i].second == x) {
        v[i].first -= y;
        break;
      }
    relax(st1, en);
  }
  ar[x].second -= y;
}
void query3() {
  pair<int, int> ans(-1, -1);
  for (int i = 0; i < (int)v.size(); i += SQ) {
    int en = min(i + SQ, (long long)v.size());
    pair<int, int> hp = v[en - 1];
    if (hp.first > ans.first)
      ans = hp;
    else if (ans.first == hp.first && hp.second < ans.second)
      ans = hp;
  }
  if (ans.first == -1) {
    cout << 0 << endl;
    return;
  }
  cout << ans.first << endl;
  query2(ans.second, ans.first + 1);
}
int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  cin >> h >> n >> m >> k;
  for (int i = 0; i < n; i++) {
    cin >> ar[i].first >> ar[i].second;
    ar[i].first--;
  }
  for (int i = 0; i < MAXk; i++) can[i] = INF;
  can[0] = 0;
  update();
  for (int i = 0; i < m; i++) {
    int a;
    cin >> a;
    if (a == 1) {
      long long hp;
      cin >> hp;
      query1(hp);
    } else if (a == 2) {
      int x, y;
      cin >> x >> y;
      x--;
      query2(x, y);
    } else {
      query3();
    }
  }
}
