#include <bits/stdc++.h>
#pragma GCC optimize("O2,Ofast,inline,unroll-all-loops,-ffast-math")
#pragma GCC target("avx,sse2,sse3,sse4,popcnt")
using namespace std;
struct data {
  int a, b, c;
  bool operator<(const data &rhs) const { return a < rhs.a; }
} ds[500010];
struct pnt {
  int x, y;
  long long ans;
  pnt(int _x = 0, int _y = 0, long long _ans = 0) {
    x = _x, y = _y, ans = _ans;
  }
  bool operator<(const pnt &rhs) const {
    return x == rhs.x ? y < rhs.y : x < rhs.x;
  }
};
int mb[500010], mc[500010], n, A, B, C;
long long tot = 0;
set<pnt> st;
template <class T>
void read(T &x) {
  char ch = x = 0;
  bool fl = false;
  while (!isdigit(ch)) fl |= ch == '-', ch = getchar();
  while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
  x = fl ? -x : x;
}
int calc(int x, int y) { return x > y ? 0 : y - x; }
void erase(pnt tmp) { tot -= tmp.ans, st.erase(tmp); }
void insert(pnt tmp) { tot += tmp.ans, st.insert(tmp); }
void Insert(pnt tmp) {
  auto it = st.lower_bound(tmp);
  if (it->y >= tmp.y) return;
  pnt nxt = *it;
  while (1) {
    it = st.lower_bound(tmp);
    if (it == st.begin()) {
      tmp.ans = 1LL * tmp.y * tmp.x;
      break;
    }
    if ((--it)->y > tmp.y) {
      tmp.ans = 1LL * tmp.y * (tmp.x - it->x);
      break;
    }
    erase(*it);
  }
  erase(nxt), insert(pnt(nxt.x, nxt.y, 1LL * nxt.y * (nxt.x - tmp.x))),
      insert(tmp);
}
int main() {
  read(n), read(A), read(B), read(C);
  for (int i = 1; i <= n; i++) read(ds[i].a), read(ds[i].b), read(ds[i].c);
  sort(ds + 1, ds + n + 1), ds[n + 1].a = A;
  for (int i = n; i; i--)
    mb[i] = max(mb[i + 1], ds[i].b), mc[i] = max(mc[i + 1], ds[i].c);
  long long ans = 0;
  st.insert(pnt(0, C + 1, 0)), st.insert(pnt(B + 1, 0, 0));
  for (int i = 1; i <= n; i++) Insert(pnt(ds[i].b, ds[i].c));
  for (int i = n; i; i--) {
    ans += 1LL * calc(ds[i].a, ds[i + 1].a) * tot;
    Insert(pnt(ds[i].b, C)), Insert(pnt(B, ds[i].c));
  }
  ans += 1LL * calc(0, ds[1].a) * tot;
  printf("%lld\n", 1LL * A * B * C - ans);
  return 0;
}
