#include <bits/stdc++.h>
using ll = long long;
const int C = 500001, Cv = 1 << 20;
const ll Inf = 1000000000000000001ll;
ll pom[C], pom2[C], pom3[C];
void Sebasort(ll tab[], ll tab2[], ll tab3[], int l, int r) {
  int lim = 2, limi = l + 1, limj = l + 2, j = limi, i = l, k = l;
  while (lim / 2 <= r - l + 1) {
    while (i <= r) {
      if (limj > r) limj = r + 1;
      if ((j < limj && tab[j] < tab[i]) || i >= limi)
        pom[k] = tab[j], pom2[k] = tab2[j], pom3[k] = tab3[j], j++;
      else
        pom[k] = tab[i], pom2[k] = tab2[i], pom3[k] = tab3[i], i++;
      k++;
      if (i == limi && j == limj) limi += lim, limj += lim, i = j, j = limi;
    }
    for (i = l; i <= r; i++)
      tab[i] = pom[i], tab2[i] = pom2[i], tab3[i] = pom3[i];
    lim *= 2, limi = l + lim / 2, limj = l + lim, j = limi, i = k = l;
  }
}
ll a_f, b_f, c_f;
ll a[C], b[C], c[C], c_val[C];
ll present_max[Cv << 1], present_min[Cv << 1], max_value_of_c[Cv << 1],
    summa[Cv << 1];
ll mx_b[C], mx_c[C];
int query_above(int b) {
  int i;
  if (present_max[1] < b) return -1;
  for (i = 1; i < Cv;) {
    if (present_max[i * 2] >= b)
      i = i * 2;
    else
      i = i * 2 + 1;
  }
  return i - Cv;
}
int query_c_above(ll c) {
  int i;
  if (max_value_of_c[1] < c) return -1;
  for (i = 1; i < Cv;) {
    if (max_value_of_c[i * 2 + 1] >= c)
      i = i * 2 + 1;
    else
      i = i * 2;
  }
  return i - Cv;
}
int query_below(int b) {
  int i;
  if (present_min[1] > b) return -1;
  for (i = 1; i < Cv;) {
    if (present_min[i * 2 + 1] <= b)
      i = i * 2 + 1;
    else
      i = i * 2;
  }
  return i - Cv;
}
void update_position(int a) {
  for (a /= 2; a > 0; a /= 2) {
    present_min[a] = (((present_min[a * 2]) < (present_min[a * 2 + 1]))
                          ? (present_min[a * 2])
                          : (present_min[a * 2 + 1]));
    present_max[a] = (((present_max[a * 2]) > (present_max[a * 2 + 1]))
                          ? (present_max[a * 2])
                          : (present_max[a * 2 + 1]));
  }
}
void insert_c_val(int b, ll c, ll ln) {
  int a = b + Cv;
  c_val[b] = c;
  summa[a] = c * ln;
  max_value_of_c[a] = c;
  for (a /= 2; a > 0; a /= 2) {
    summa[a] = summa[a * 2] + summa[a * 2 + 1];
    max_value_of_c[a] = (((max_value_of_c[a * 2]) > (max_value_of_c[a * 2 + 1]))
                             ? (max_value_of_c[a * 2])
                             : (max_value_of_c[a * 2 + 1]));
  }
}
void remove_c_val(int b) {
  int a = b + Cv;
  c_val[b] = 0;
  summa[a] = 0;
  max_value_of_c[a] = -1;
  for (a /= 2; a > 0; a /= 2) {
    summa[a] = summa[a * 2] + summa[a * 2 + 1];
    max_value_of_c[a] = (((max_value_of_c[a * 2]) > (max_value_of_c[a * 2 + 1]))
                             ? (max_value_of_c[a * 2])
                             : (max_value_of_c[a * 2 + 1]));
  }
}
void remove_from_position(int b) {
  int a = b + Cv;
  present_min[a] = Inf, present_max[a] = -1;
  update_position(a);
  remove_c_val(b);
}
void insert_into_position(int b) {
  int a = b + Cv;
  present_min[a] = b, present_max[a] = b;
  update_position(a);
}
void insert_wrapper(int b, int c) {
  int x, y;
  y = query_above(b);
  if (y != -1 && c_val[y] >= c) return;
  while (true) {
    x = query_below(b);
    if (x != -1 && c_val[x] <= c)
      remove_from_position(x);
    else
      break;
  }
  insert_into_position(b);
  if (x == -1) x = 0;
  insert_c_val(b, c, b - x);
  y = query_above(b + 1);
  if (y != -1) insert_c_val(y, c_val[y], y - b);
}
ll summarize(int a, int b) {
  int l = a + Cv, r = b + Cv;
  ll res = 0;
  if (l != r)
    res = summa[l] + summa[r];
  else
    res = summa[l];
  for (; l > 0; l /= 2, r /= 2) {
    if (l % 2 == 0 && r - l > 1) res += summa[l + 1];
    if (r % 2 == 1 && r - l > 1) res += summa[r - 1];
  }
  return res;
}
ll query_wrapper(int b, ll c) {
  int last_b = query_c_above(c);
  int b0 = query_above(b), b1;
  ll res = 0, botched_part = 0;
  b1 = query_above(b0 + 1);
  if (last_b != -1 && last_b >= b) {
    if (b1 != -1 && b1 <= last_b) res = summarize(b1, last_b);
    res = res + 1ll * (b0 - b) * c_val[b0];
    botched_part = res - 1ll * c * (last_b - b);
  } else
    botched_part = 0;
  return 1ll * (b_f - b) * (c_f - c) - botched_part;
}
int main() {
  int n, i, a_diff;
  ll res = 0, last_a;
  scanf("%d %lld %lld %lld", &n, &a_f, &b_f, &c_f);
  for (i = 0; i < n; i++) {
    scanf("%lld %lld %lld", &a[i], &b[i], &c[i]);
  }
  Sebasort(a, b, c, 0, n - 1);
  for (i = n - 1; i >= 0; i--) {
    mx_b[i] = (((b[i]) > (mx_b[i + 1])) ? (b[i]) : (mx_b[i + 1]));
    mx_c[i] = (((c[i]) > (mx_c[i + 1])) ? (c[i]) : (mx_c[i + 1]));
  }
  for (i = 0; i < 2 * Cv; i++)
    present_min[i] = Inf, present_max[i] = -1, max_value_of_c[i] = -1;
  last_a = 1;
  for (i = 0; i < n;) {
    a_diff = a[i] - last_a + 1;
    res = res + a_diff * query_wrapper(mx_b[i], mx_c[i]);
    last_a = a[i] + 1;
    while (a[i] == a[i + 1] && i < n) {
      insert_wrapper(b[i], c[i]);
      i++;
    }
    insert_wrapper(b[i], c[i]);
    i++;
  }
  a_diff = a_f - last_a + 1;
  res = res + a_diff * query_wrapper(0, 0);
  printf("%lld\n", res);
  return 0;
}
