#include <bits/stdc++.h>
using namespace std;
struct card {
  long long a, b, c;
} c[500002];
bool operator<(card a, card b) { return a.a < b.a; }
long long n, p, q, r, pnt = 1, ans, s[500002], t[500002];
struct segment_tree {
  struct node_type {
    long long l, r, val, max, sum, tag;
    node_type *child[2];
  } * root;
  void build_tree(node_type *root) {
    if (root->l == root->r) return;
    long long mid = root->l + root->r >> 1;
    node_type *p, *q;
    p = new node_type;
    p->l = root->l, p->r = mid, p->val = p->max = p->sum = p->tag = 0;
    q = new node_type;
    q->l = mid + 1, q->r = root->r, q->val = q->max = q->sum = q->tag = 0;
    build_tree(p), build_tree(q);
    root->child[0] = p, root->child[1] = q;
  }
  void push_up(node_type *root) {
    if (root->l != root->r) {
      root->sum = root->child[0]->sum + root->child[1]->sum;
      root->max = max(root->child[0]->max, root->child[1]->max);
    }
  }
  void push_down(node_type *root) {
    if (root->tag && root->l != root->r) {
      root->child[0]->tag = root->child[0]->max = root->child[1]->tag =
          root->child[1]->max = root->tag;
      root->child[0]->sum = (root->child[1]->l - root->child[0]->l) * root->tag;
      root->child[1]->sum = (root->child[1]->r - root->child[0]->r) * root->tag;
    }
    root->tag = 0;
  }
  void insert_line(node_type *root, long long l, long long r, long long t) {
    if (l == root->l && r == root->r) {
      root->tag = root->max = t;
      root->sum = (r - l + 1) * t;
      return;
    }
    push_down(root);
    if (r < root->child[1]->l)
      insert_line(root->child[0], l, r, t);
    else if (l > root->child[0]->r)
      insert_line(root->child[1], l, r, t);
    else {
      insert_line(root->child[0], l, root->child[0]->r, t);
      insert_line(root->child[1], root->child[1]->l, r, t);
    }
    push_up(root);
  }
  long long get(node_type *root, long long t) {
    if (root->l == root->r) return root->l;
    push_down(root);
    if (root->child[1]->max < t)
      return get(root->child[0], t);
    else
      return get(root->child[1], t);
  }
  long long get_sum(node_type *root, int l, int r) {
    if (l == root->l && r == root->r) return root->sum;
    push_down(root);
    if (r < root->child[1]->l)
      return get_sum(root->child[0], l, r);
    else if (l > root->child[0]->r)
      return get_sum(root->child[1], l, r);
    else
      return get_sum(root->child[0], l, root->child[0]->r) +
             get_sum(root->child[1], root->child[1]->l, r);
  }
} tree;
int main() {
  scanf("%lld%lld%lld%lld", &n, &p, &q, &r);
  tree.root = new segment_tree::node_type;
  tree.root->l = 0, tree.root->r = q,
  tree.root->val = tree.root->max = tree.root->sum = tree.root->tag = 0;
  tree.build_tree(tree.root);
  for (int i = 1; i <= n; ++i) {
    scanf("%lld%lld%lld", &c[i].a, &c[i].b, &c[i].c);
  }
  sort(c + 1, c + n + 1);
  s[n] = c[n].b, t[n] = c[n].c;
  for (int i = n - 1; i; --i) {
    s[i] = max(s[i + 1], c[i].b);
    t[i] = max(t[i + 1], c[i].c);
  }
  tree.insert_line(tree.root, 0, 0, q + 1);
  long long tmp;
  for (int i = 1, j = 1; i <= p; ++i) {
    for (; j <= n && c[j].a < i; ++j) {
      tmp = tree.get(tree.root, c[j].c);
      if (tmp >= c[j].b) continue;
      tree.insert_line(tree.root, tmp + 1, c[j].b, c[j].c);
    }
    tmp = max(s[j], tree.get(tree.root, t[j] + 1));
    ans += (tmp - s[j]) * r + (q - tmp) * (r - t[j]);
    if (tmp > s[j]) ans -= tree.get_sum(tree.root, s[j] + 1, tmp);
  }
  printf("%lld\n", ans);
  return 0;
}
