#include <bits/stdc++.h>   using namespace std;   const int M = 100000 + 5;   map<long long int, int> mp;   queue<int> Q;   int vis[M];   long long int dk[M];   vector<long long int> step;   long long int a[M];   int rch[M];   struct TREE {     int lc;     int rc;     long long int l;     long long int r;     long long int idx;     long long int val;   } tree[20 * M];   int tot = 1;   void update(long long int l, long long int r, int node, long long int val,               long long int idx) {     if (l == r) {       tree[node].val += val;       tree[node].l = l;       tree[node].r = r;       tree[node].idx = idx;       tree[node].lc = node;       tree[node].rc = node;       return;     }     long long int m = (l + r) / 2;     if (tree[node].lc == 0) {       tot++;       tree[node].lc = tot;     }     if (tree[node].rc == 0) {       tot++;       tree[node].rc = tot;     }     if (idx <= m) {       update(l, m, tree[node].lc, val, idx);     } else {       update(m + 1, r, tree[node].rc, val, idx);     }     int lc = tree[node].lc;     int rc = tree[node].rc;     if (tree[lc].val < tree[rc].val) {       tree[node].idx = tree[rc].idx;       tree[node].val = tree[rc].val;     } else {       tree[node].idx = tree[lc].idx;       tree[node].val = tree[lc].val;     }     return;   }   int main() {     time_t t_start, t_end;     t_start = clock();     long long int h;     cin >> h;     int n, m, k;     cin >> n >> m >> k;     for (int i = 0; i < n; i++) {       long long int ai;       int ci;       cin >> ai >> ci;       a[i + 1] = ai;       mp[ai] = ci;       if (ai % k == 1) {         rch[i + 1] = 1;         update(1, M, 1, ci, i + 1);       }     }     step.push_back(k);     for (int q = 0; q < m; q++) {       int ty;       cin >> ty;       if (ty == 1) {         long long int x;         cin >> x;         step.push_back(x);         for (int i = 0; i < M; i++) {           vis[i] = 0;           dk[i] = -1;         }         Q.push(1);         dk[1] = 0;         while (!Q.empty()) {           int u = Q.front();           vis[u] = 0;           Q.pop();           for (int i = 0; i < step.size(); i++) {             long long int dx = step[i];             int nxtu = (u + dx) % k;             long long int nxty = (u + dk[u] * k + dx) / k;             if (dk[nxtu] == -1 || dk[nxtu] > nxty) {               dk[nxtu] = nxty;               if (vis[nxtu] == 0) {                 Q.push(nxtu);                 vis[nxtu] = 1;               }             }           }         }         for (int i = 1; i <= n; i++) {           long long int ai = a[i];           int u = ai % k;           if (dk[u] != -1) {             long long int yy = dk[u] * k + u;             if (ai >= yy && rch[i] == 0) {               rch[i] = 1;               update(1, M, 1, mp[ai], i);             }           }         }       }       if (ty == 2) {         int x;         long long int y;         cin >> x >> y;         long long int ai = a[x];         mp[ai] = mp[ai] - y;         if (rch[x] == 1) {           update(1, M, 1, -y, x);         }       }       if (ty == 3) {         long long int res = tree[1].val;         cout << res << endl;         update(1, M, 1, -res, tree[1].idx);       }     }     t_end = clock();     return 0;   }