#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 524288;
const int oo = 1E9;
struct Node {
  int l, r;
  long long sum, small, put;
  Node() {
    sum = small = 0;
    put = -oo;
  }
};
Node tree[2 * MAX_N];
void Init() {
  for (int i = 0; i < MAX_N; ++i) tree[MAX_N + i].l = i, tree[MAX_N + i].r = i;
  for (int i = MAX_N - 1; i > 0; --i)
    tree[i].l = tree[2 * i].l, tree[i].r = tree[2 * i + 1].r;
}
void Set(int vr, long long to) {
  tree[vr].put = to;
  tree[vr].small = to;
  tree[vr].sum = (tree[vr].r - tree[vr].l + 1) * to;
}
void Push(int vr) {
  if (tree[vr].put == -oo) return;
  if (vr < MAX_N) {
    Set(2 * vr, tree[vr].put);
    Set(2 * vr + 1, tree[vr].put);
  }
  tree[vr].put = -oo;
}
void Update(int vr) {
  if (vr < MAX_N) {
    tree[vr].sum = tree[2 * vr].sum + tree[2 * vr + 1].sum;
    tree[vr].small = min(tree[2 * vr].small, tree[2 * vr + 1].small);
  }
}
void SetIval(int vr, int l, int r, int to) {
  if (r < tree[vr].l || tree[vr].r < l) return;
  Push(vr);
  if (l <= tree[vr].l && tree[vr].r <= r) {
    Set(vr, to);
  } else {
    SetIval(2 * vr, l, r, to);
    SetIval(2 * vr + 1, l, r, to);
    Update(vr);
  }
}
int FirstLE(int vr, int to) {
  if (vr >= MAX_N) return tree[vr].l;
  Push(vr);
  if (tree[2 * vr].small <= to)
    return FirstLE(2 * vr, to);
  else
    return FirstLE(2 * vr + 1, to);
}
void RelaxPreffix(int up, int to) {
  int start = FirstLE(1, to);
  if (start <= up) SetIval(1, start, up, to);
}
long long GetSum(int vr, int l, int r) {
  if (r < tree[vr].l || tree[vr].r < l) return 0;
  Push(vr);
  if (l <= tree[vr].l && tree[vr].r <= r) return tree[vr].sum;
  return GetSum(2 * vr, l, r) + GetSum(2 * vr + 1, l, r);
}
long long GetBad(int xlo, int ylo) {
  int pos = FirstLE(1, ylo);
  if (xlo < pos) {
    return GetSum(1, xlo, pos - 1) - (pos - xlo) * 1LL * ylo;
  } else {
    return 0;
  }
}
int main() {
  Init();
  int n, p, q, r;
  scanf("%d%d%d%d", &n, &p, &q, &r);
  vector<array<int, 3>> in(n);
  vector<array<int, 3>> low(n + 1);
  for (int i = 0; i < n; ++i) scanf("%d%d%d", &in[i][0], &in[i][1], &in[i][2]);
  sort(in.begin(), in.end());
  low[n][1] = 0, low[n][2] = 0;
  for (int i = n - 1; i >= 0; --i)
    low[i][1] = max(low[i + 1][1], in[i][1]),
    low[i][2] = max(low[i + 1][2], in[i][2]);
  long long ans = 0;
  int pos = 0;
  for (int a = 1; a <= p; ++a) {
    while (pos < ((int)(in).size()) && in[pos][0] < a) {
      int b = in[pos][1];
      int c = in[pos][2];
      RelaxPreffix(b, c);
      ++pos;
    }
    long long blo = low[pos][1] + 1;
    long long clo = low[pos][2] + 1;
    if (blo <= q && clo <= r) {
      long long tot = (q - blo + 1) * (r - clo + 1);
      tot -= GetBad(blo, clo - 1);
      ans += tot;
    }
  }
  cout << ans << '\n';
  return 0;
}
