Rainbow built h cells in a row that are numbered from 1 to h from left to right. There are n cells with treasure. We call each of these n cells "Treasure Cell". The i-th "Treasure Cell" is the ai-th cell and the value of treasure in it is ci dollars.

Then, Freda went in the first cell. For now, she can go just k cells forward, or return to the first cell. That means Freda was able to reach the 1st, (k + 1)-th, (2·k + 1)-th, (3·k + 1)-th cells and so on.

Then Rainbow gave Freda m operations. Each operation is one of the following three types:

  1. Add another method x: she can also go just x cells forward at any moment. For example, initially she has only one method k. If at some moment she has methods a1, a2, ..., ar then she can reach all the cells with number in form <image>, where vi — some non-negative integer. 
  2. Reduce the value of the treasure in the x-th "Treasure Cell" by y dollars. In other words, to apply assignment cx = cx - y. 
  3. Ask the value of the most valuable treasure among the cells Freda can reach. If Freda cannot reach any cell with the treasure then consider the value of the most valuable treasure equal to 0, and do nothing. Otherwise take the most valuable treasure away. If several "Treasure Cells" have the most valuable treasure, take the "Treasure Cell" with the minimum number (not necessarily with the minimum number of cell). After that the total number of cells with a treasure is decreased by one. 



As a programmer, you are asked by Freda to write a program to answer each query.

Input

The first line of the input contains four integers: h (1 ≤ h ≤ 1018), n, m (1 ≤ n, m ≤ 105) and k (1 ≤ k ≤ 104).

Each of the next n lines contains two integers: ai (1 ≤ ai ≤ h), ci (1 ≤ ci ≤ 109). That means the i-th "Treasure Cell" is the ai-th cell and cost of the treasure in that cell is ci dollars. All the ai are distinct.

Each of the next m lines is in one of the three following formats:

  * "1 x" — an operation of type 1, 1 ≤ x ≤ h; 
  * "2 x y" — an operation of type 2, 1 ≤ x ≤ n, 0 ≤ y < cx; 
  * "3" — an operation of type 3. 



There are at most 20 operations of type 1. It's guaranteed that at any moment treasure in each cell has positive value. It's guaranteed that all operations is correct (no operation can decrease the value of the taken tresure).

Please, do not use the %lld specifier to read 64-bit integers in С++. It is preferred to use the cin, cout streams or the %I64d specifier.

Output

For each operation of type 3, output an integer indicates the value (in dollars) of the most valuable treasure among the "Treasure Cells" Freda can reach. If there is no such treasure, output 0.

Examples

Input

10 3 5 2
5 50
7 60
8 100
2 2 5
3
1 3
3
3


Output

55
100
50

Note

In the sample, there are 10 cells and 3 "Treasure Cells". The first "Treasure Cell" is cell 5, having 50 dollars tresure in it. The second "Treasure Cell" is cell 7, having 60 dollars tresure in it. The third "Treasure Cell" is cell 8, having 100 dollars tresure in it.

At first, Freda can only reach cell 1, 3, 5, 7 and 9. In the first operation, we reduce the value in the second "Treasure Cell" from 60 to 55. Then the most valuable treasure among the "Treasure Cells" she can reach is max(50, 55) = 55. After the third operation, she can also go 3 cells forward each step, being able to reach cell 1, 3, 4, 5, 6, 7, 8, 9, 10. So the most valuable tresure is 100.

Noticed that she took the 55 dollars and 100 dollars treasure away, so the last answer is 50.
#include <bits/stdc++.h>
using namespace std;
struct pkt {
  long long x, c;
  bool jest;
};
const long long INF = 1000000000000000000;
void Dijkstra(long long k, vector<long long>& skoki,
              set<pair<long long, long long> >& S, vector<pkt>& a) {
  vector<long long> D(k, INF);
  D[0] = 0;
  set<pair<long long, long long> > Q;
  for (int i = 0; i < k; ++i) Q.insert(make_pair(D[i], i));
  while (Q.size() != 0) {
    pair<long long, long long> akt = *Q.begin();
    Q.erase(Q.begin());
    for (int i = 0; i < skoki.size(); ++i) {
      long long nowa_dl = akt.first + skoki[i];
      if (nowa_dl < D[nowa_dl % k]) {
        D[nowa_dl % k] = nowa_dl;
        Q.insert(make_pair(nowa_dl, nowa_dl % k));
      }
    }
  }
  for (int i = 0; i < a.size(); ++i) {
    if (!a[i].jest && D[a[i].x % k] <= a[i].x) {
      S.insert(make_pair(-a[i].c, i));
      a[i].jest = true;
    }
  }
}
int main() {
  ios_base::sync_with_stdio(0);
  long long h, n, m, k;
  cin >> h >> n >> m >> k;
  vector<pkt> a(n);
  for (int i = 0; i < n; ++i) {
    cin >> a[i].x >> a[i].c;
    --a[i].x;
    a[i].jest = false;
  }
  vector<long long> skoki;
  skoki.push_back(k);
  set<pair<long long, long long> > S;
  Dijkstra(k, skoki, S, a);
  for (int i = 0; i < m; ++i) {
    int op;
    cin >> op;
    if (op == 1) {
      long long x;
      cin >> x;
      skoki.push_back(x);
      Dijkstra(k, skoki, S, a);
    }
    if (op == 2) {
      long long x, y;
      cin >> x >> y;
      --x;
      if (S.find(make_pair(-a[x].c, x)) != S.end()) {
        S.erase(make_pair(-a[x].c, x));
        S.insert(make_pair(-a[x].c + y, x));
      }
      a[x].c -= y;
    }
    if (op == 3) {
      if (S.size() != 0) {
        pair<long long, long long> t = *S.begin();
        cout << -t.first << endl;
        S.erase(S.begin());
      } else
        cout << "0" << endl;
    }
  }
  return 0;
}
