#define NDEBUG
#include <bits/stdc++.h>
using namespace std;
using lint = long long;
template<class T = int> using V = vector<T>;
template<class T = int> using VV = V< V<T> >;


template<class T> struct PrimalDual {
  struct Edge {
    int to, rev;
    T cap, cost;
  };
  const int n;
  const T inf = numeric_limits<T>::max();
  VV<Edge> g;
  V<T> pot, dist;
  V<> pv, pe;
  PrimalDual(int n) : n(n), g(n), pot(n), dist(n), pv(n), pe(n) {}
  void add_edge(int from, int to, T cap, T cost) {
    assert(from != to);
    assert(cap >= 0);
    assert(cost >= 0);
    g[from].emplace_back(Edge{to, (int) g[to].size(), cap, cost});
    g[to].emplace_back(Edge{from, (int) g[from].size() - 1, 0, -cost});
  }
  void dijkstra(int s) {
    using P = pair<T, int>;
    priority_queue< P, V<P>, greater<P> > pque;
    fill(begin(dist), end(dist), inf);
    pque.emplace(dist[s] = 0, s);
    while (!pque.empty()) {
      T d; int v;
      tie(d, v) = pque.top(); pque.pop();
      if (d > dist[v]) continue;
      for (int i = 0; i < g[v].size(); ++i) {
        const Edge& e = g[v][i];
        if (e.cap <= 0 or dist[e.to] <= dist[v] + e.cost - (pot[e.to] - pot[v])) continue;
        pv[e.to] = v;
        pe[e.to] = i;
        pque.emplace(dist[e.to] = dist[v] + e.cost - (pot[e.to] - pot[v]), e.to);
      }
    }
  }
  T min_cost_flow(int s, int t, T f) {
    assert(s != t);
    assert(f >= 0);
    T res = 0;
    // fill(begin(pot), end(pot), 0);
    while (f > 0) {
      dijkstra(s);
      if (dist[t] == inf) return -1;
      for (int v = 0; v < n; ++v) pot[v] += dist[v];
      T d = f;
      for (int v = t; v != s; v = pv[v]) {
        d = min(d, g[pv[v]][pe[v]].cap);
      }
      f -= d;
      res += d * pot[t];
      for (int v = t; v != s; v = pv[v]) {
        Edge& e = g[pv[v]][pe[v]];
        e.cap -= d;
        g[v][e.rev].cap += d;
      }
    }
    return res;
  }
};

int main() {
  cin.tie(nullptr); ios::sync_with_stdio(false);
  int n, v, xl, xr; cin >> n >> v >> xl >> xr;
  PrimalDual<int> g(2 * n + 4);
  int sl = 2 * n, sr = 2 * n + 1, S = 2 * n + 2, T = 2 * n + 3;
  g.add_edge(S, sl, 1, 0);
  g.add_edge(sl, T, 1, 0);
  g.add_edge(S, sr, 1, 0);
  g.add_edge(sr, T, 1, 0);
  V<> x(n), t(n), p(n);
  for (int i = 0; i < n; ++i) {
    cin >> x[i] >> t[i] >> p[i];
    if (abs(x[i] - xl) <= v * t[i]) {
      g.add_edge(sl, 2 * i, 1, 0);
    }
    if (abs(x[i] - xr) <= v * t[i]) {
      g.add_edge(sr, 2 * i, 1, 0);
    }
    g.add_edge(2 * i + 1, T, 1, 0);
    g.add_edge(2 * i, 2 * i + 1, 1, -p[i]);
  }
  for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) if (t[i] < t[j]) {
    if (abs(x[j] - x[i]) <= v * (t[j] - t[i])) {
      g.add_edge(2 * i + 1, 2 * j, 1, 0);
    }
  }
  V<> idx{S, sl, sr};
  {
    V<> ii(n);
    iota(begin(ii), end(ii), 0);
    sort(begin(ii), end(ii), [&](int i, int j) { return t[i] < t[j]; });
    for (int i : ii) {
      idx.push_back(2 * i);
      idx.push_back(2 * i + 1);
    }
    idx.push_back(T);
    assert(idx.size() == g.size());
  }
  g.pot[S] = 0;
  for (int i : idx) {
    for (const auto& e : g.g[i]) if (e.cap > 0) {
      g.pot[e.to] = min(g.pot[e.to], g.pot[i] + e.cost);
    }
  }
  cout << -g.min_cost_flow(S, T, 2) << '\n';
}


Measured memory_bytes: 241428