#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 1 << 20;
int n, p, q, r;
int a[MAXN], b[MAXN], c[MAXN];
struct O {
  int Pos, x, c;
  bool operator<(const O& oo) const { return c > oo.c; }
} OP[MAXN];
struct Node {
  int mitag, tag, C;
  long long S;
} ST[MAXN];
void inline pushup(int k) {
  ST[k].mitag = min(ST[(k << 1)].mitag, ST[(k << 1 | 1)].mitag);
  ST[k].C = ST[(k << 1)].C + ST[(k << 1 | 1)].C;
  ST[k].S = ST[(k << 1)].S + ST[(k << 1 | 1)].S;
}
void dfs(int k, int l, int r, int x) {
  if (ST[k].mitag >= x) return;
  ST[k].tag = -1, ST[k].mitag = INF;
  if (r - l <= 1) {
    ST[k].C = 0, ST[k].S = 0;
    return;
  }
  int m = l + r >> 1;
  dfs((k << 1), l, m, x);
  dfs((k << 1 | 1), m, r, x);
  pushup(k);
}
void inline puttag(int k, int l, int r, int x) {
  if (ST[k].tag != -1 && ST[k].tag >= x) return;
  if (ST[k].C != r - l) {
    ST[k].tag = x;
    ST[k].mitag = x;
    ST[k].S += 1ll * (r - l - ST[k].C) * x;
    ST[k].C = r - l;
  }
}
void inline pushdown(int k, int l, int r) {
  if (ST[k].tag == -1) return;
  int m = l + r >> 1;
  puttag((k << 1), l, m, ST[k].tag);
  puttag((k << 1 | 1), m, r, ST[k].tag);
  ST[k].tag = -1;
}
void modify(int k, int l, int r, int ql, int qr, int x) {
  if (ql >= r || qr <= l || ST[k].mitag >= x) return;
  if (ql <= l && r <= qr) {
    dfs(k, l, r, x);
    puttag(k, l, r, x);
    return;
  }
  int m = l + r >> 1;
  pushdown(k, l, r);
  modify((k << 1), l, m, ql, qr, x);
  modify((k << 1 | 1), m, r, ql, qr, x);
  pushup(k);
}
long long Query(int k, int l, int r, int ql, int qr) {
  if (ql >= r || qr <= l) return 0;
  if (ql <= l && r <= qr) return ST[k].S;
  int m = l + r >> 1;
  pushdown(k, l, r);
  long long res =
      Query((k << 1), l, m, ql, qr) + Query((k << 1 | 1), m, r, ql, qr);
  pushup(k);
  return res;
}
void build(int k, int l, int r) {
  ST[k].mitag = INF, ST[k].tag = -1, ST[k].S = 0, ST[k].C = 0;
  if (r == l) {
    return;
  } else if (r == l + 1) {
    ST[k].tag = 0;
    ST[k].C = 1;
    ST[k].S = 0, ST[k].mitag = 0;
    return;
  }
  int m = l + r >> 1;
  build((k << 1), l, m);
  build((k << 1 | 1), m, r);
  pushup(k);
}
long long ans;
int main() {
  scanf("%d%d%d%d", &n, &p, &q, &r);
  build(1, 1, q + 1);
  for (int i = (0); i < (n); i++) {
    scanf("%d%d%d", a + i, b + i, c + i);
    modify(1, 1, q + 1, 1, b[i] + 1, a[i]);
    OP[i].Pos = b[i];
    OP[i].x = a[i];
    OP[i].c = c[i];
  }
  sort(OP, OP + n);
  int j = 0;
  for (int i = (r + 1) - 1; i >= (1); i--) {
    while (j < n && OP[j].c >= i) {
      modify(1, 1, q + 1, 1, OP[j].Pos + 1, p);
      modify(1, 1, q + 1, OP[j].Pos + 1, q + 1, OP[j].x);
      j++;
    }
    ans += Query(1, 1, q + 1, 1, q + 1);
  }
  ans = 1ll * p * q * r - ans;
  cout << ans << endl;
}
