#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <functional>
#include <climits>
struct Mole {
	int position, time, score;
	Mole(const int x, const int t, const int p) : position{ x }, time{ t }, score{ p }{};
	Mole() :Mole(0, 0, 0) {};
};
struct Edge {
	int to, pair, cost;
	bool flow;
	Edge(int t, int p, int c, bool f) : to{ t }, pair{ p }, cost{ c }, flow{ f }{};
	Edge() : Edge(0, 0, 0, false) {}
};
void setEdge(const int from, const int to, const int cost, std::vector<std::vector<Edge>>& nodes) {
	nodes[from].push_back(Edge(to, nodes[to].size(), cost, true));
	nodes[to].push_back(Edge(from, nodes[from].size() - 1, -cost, false));
}
int solve(const long velocity, const int left, const int right, const std::vector<Mole>& mole) {
	std::vector<std::vector<Edge>> nodes(mole.size() * 2 + 4);
	const int start_left = nodes.size() - 4;
	const int start_right = nodes.size() - 3;
	const int start = nodes.size() - 2;
	const int goal = nodes.size() - 1;
	setEdge(start, start_left, 0, nodes);
	setEdge(start, start_right, 0, nodes);
	std::vector<int> sum_cost(mole.size() + 1, 0);
	for (auto i = 1; i < sum_cost.size(); ++i) sum_cost[i] = sum_cost[i - 1] + mole[i - 1].score;
	setEdge(start_left, goal, sum_cost.back(), nodes);
	setEdge(start_right, goal, sum_cost.back(), nodes);
	for (auto i = 0; i < mole.size(); ++i) {
		auto m = mole[i];
		if (std::abs(left - m.position) <= m.time * velocity) {
			setEdge(start_left, i * 2, sum_cost[i], nodes);
		}
		if (std::abs(right - m.position) <= m.time * velocity) {
			setEdge(start_right, i * 2, sum_cost[i], nodes);
		}
		setEdge(i * 2, i * 2 + 1, 0, nodes);
		setEdge(i * 2 + 1, goal, sum_cost.back() - sum_cost[i + 1], nodes);
	}
	for (auto i = 0; i < mole.size(); ++i) {
		for (auto j = i + 1; j < mole.size(); ++j) {
			if (std::abs(mole[i].position - mole[j].position) <= (mole[j].time - mole[i].time) * velocity) {
				setEdge(i * 2 + 1, j * 2, sum_cost[j] - sum_cost[i + 1], nodes);
			}
		}
	}
	std::vector<int> potential(nodes.size(), 0);
	std::vector<int> min_cost(nodes.size(), 0);
	std::priority_queue<std::tuple<int, int>, std::vector<std::tuple<int, int>>, std::function<bool(const std::tuple<int, int>&, const std::tuple<int, int>&)>> empty_queue([](const std::tuple<int, int> & a, const std::tuple<int, int> & b) {return std::get<1>(a) > std::get<1>(b); });
	std::vector<Edge> prev_edge(nodes.size());
	int result = 0;
	for (auto repeat = 0; repeat < 2; ++repeat) {
		for (auto i = 0; i < min_cost.size(); ++i) min_cost[i] = INT_MAX;
		auto queue = empty_queue;
		min_cost[start] = 0;
		queue.push(std::make_tuple(start, 0));
		while (std::get<0>(queue.top()) != goal) {
			auto current = std::get<0>(queue.top());
			auto cost = std::get<1>(queue.top());
			queue.pop();
			if (min_cost[current] == cost) {
				for (const auto next : nodes[current]) if (next.flow) {
					if (min_cost[next.to] > cost + potential[current] - potential[next.to] + next.cost) {
						min_cost[next.to] = cost + potential[current] - potential[next.to] + next.cost;
						prev_edge[next.to] = next;
						queue.push(std::make_tuple(next.to, min_cost[next.to]));
					}
				}
			}
		}
		result += sum_cost.back() - min_cost[goal];
		auto last = goal;
		while (last != start) {
			auto edge = prev_edge[last];
			auto& rev = nodes[edge.to][edge.pair];
			rev.flow = true;
			nodes[rev.to][rev.pair].flow = false;
			last = rev.to;
		}
		for (auto i = 0; i < start; ++i) potential[i] += min_cost[i];
	}
	return result;
}
int main() {
	int n, v, left, right; std::cin >> n >> v >> left >> right;
	std::vector<Mole> mole(n);
	for (auto& m : mole) std::cin >> m.position >> m.time >> m.score;
	std::sort(mole.begin(), mole.end(), [](const Mole a, const Mole b) {return a.time < b.time; });
	std::cout << solve(v, left, right, mole) << std::endl;
}


Measured memory_bytes: 240728