#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <vector>
#include <queue>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))


typedef int Weight;
struct Edge {
  int index;
  int src;
  int dest;
  Weight cost;
  Edge(int index, int src, int dest, Weight cost) : index(index), src(src), dest(dest), cost(cost) {;}
  bool operator<(const Edge &rhs) const {
    return cost > rhs.cost;
  }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void printMatrix(const Matrix &matrix) {
  for (int y = 0; y < (int)matrix.size(); y++) {
    for (int x = 0; x < (int)matrix[y].size(); x++) {
      printf("%d ", matrix[y][x]);
    }
    puts("");
  }
}

vector<bool> capacity;
// index^1 is reverse edge
pair<Weight, Weight> MinCostFlow(const Graph &g, int e, int s, int t) {
  const int n = g.size();
  //Array capacity(e, 0);
  pair<Weight, Weight> ret = make_pair(0, 0);
  vector<pair<int, int> > parent(n);
  vector<Weight> prev_dist(n, 0);
  vector<Weight> now_dist(n);

  // calc potential
  for (int iter = 0; iter < n; iter++) {
    bool end = true;
    for (int from = 0; from < n; from++) {
      for (int i = 0; i < (int)g[from].size(); i++) {
        if (!capacity[g[from][i].index]) { continue; }
        int to = g[from][i].dest;
        Weight ncost = prev_dist[from] + g[from][i].cost;
        if (ncost < prev_dist[to]) {
          end = false;
          prev_dist[to] = ncost;
        }
      }
    }
    if (end) { break; }
    if (iter == n - 1) {
      assert(false); // exist negative cycle
    }
  }

  while (true) {
    fill(parent.begin(), parent.end(), make_pair(-1, -1));
    fill(now_dist.begin(), now_dist.end(), 2000000000LL);
    priority_queue<Edge> que;
    que.push(Edge(e, s, s, 0));
    now_dist[s] = 0;
    while (!que.empty()) {
      Edge node = que.top();
      que.pop();
      if (parent[node.dest].first != -1) { continue; }
      parent[node.dest] = make_pair(node.src, node.index);
      int from = node.dest;
      for (int i = 0; i < (int)g[from].size(); i++) {
        int to = g[from][i].dest;
        int index = g[from][i].index;
        Weight ncost = node.cost + g[from][i].cost + (prev_dist[from] - prev_dist[to]);
        if (!capacity[index]) { continue; }
        if (ncost >= now_dist[to]) { continue; }
        now_dist[to] = ncost;
        que.push(Edge(i, from, to, ncost));
      }
    }
    if (parent[t].first == -1) { break; }
    pair<int, int> index = parent[t];
    ret.first += 1;
    index = parent[t];
    while (index.second != e) {
      Edge edge = g[index.first][index.second];
      ret.second += edge.cost;
      capacity[edge.index] = false;
      capacity[edge.index^1] = true;
      index = parent[index.first];
    }
    for (int i = 0; i < n; i++) {
      prev_dist[i] += now_dist[i];
    }
  }
  return ret;
}

void AddEdge(Graph &g, int &e, int from, int to, Weight cost) {
  g[from].push_back(Edge(e++, from, to, cost));
  g[to].push_back(Edge(e++, to, from, -cost));
  capacity.push_back(true);
  capacity.push_back(false);
}

struct Mogura {
  int x;
  int t;
  int p;
  Mogura() {;}
  Mogura(int x, int t, int p) : x(x), t(t), p(p) {;}
  bool operator<(const Mogura &rhs) const {
    return t < rhs.t;
  }
};

int n, v, xl, xr;
Mogura mogura[3010];

inline int IN(int x) { return 2 * x + 0; }
inline int OUT(int x) { return 2 * x + 1; }
inline int SOURCE() { return n * 2; }
inline int DEST() { return n * 2 + 1; }
inline int SIZE() { return n * 2 + 2; }

int main() {
  while (scanf("%d %d %d %d", &n, &v, &xl, &xr) > 0) {
    capacity.clear();
    int e = 0;
    REP(i, n) {
      scanf("%d %d %d", &mogura[i].x, &mogura[i].t, &mogura[i].p);
    }
    mogura[n] = Mogura(xl, 0, 0);
    mogura[n + 1] = Mogura(xr, 0, 0);
    n += 2;
    sort(mogura, mogura + n);
    Graph g(SIZE());
    AddEdge(g, e, SOURCE(), IN(0), 0);
    AddEdge(g, e, SOURCE(), IN(1), 0);
    REP(i, n) {
      AddEdge(g, e, IN(i), OUT(i), -mogura[i].p);
      AddEdge(g, e, OUT(i), DEST(), 0);
    }
    REP(from, n) {
      FOR(to, from + 1, n) {
        if ((mogura[to].t - mogura[from].t) * v >= abs(mogura[to].x - mogura[from].x)) {
          AddEdge(g, e, OUT(from), IN(to), 0);
        }
      }
    }
    int ans = -MinCostFlow(g, e, SOURCE(), DEST()).second;
    cout << ans << endl;
  }
}

Measured memory_bytes: 0