Problem:
A: Attack the Moles
ICPC で良い成績を収めるには修行が欠かせない．うさぎは ICPC で勝ちたいので，今日も修行をすることにした．
今日の修行は，もぐらたたきを何回も行って，反射神経と記憶力を高めようというものである．出てくるもぐらを次々に叩き，出来るだけ多くのポイントを獲得したい．
もぐらが出てくる可能性のある場所は直線状に並んでいて，基準点からの距離によって座標が定まっている．うさぎはしばらく修行を続けるうちに，もぐらの出現する場所と時間が常に一緒であることに気が付いた．うさぎは，その情報をすべて記録し，コンピュータで解析を行うことにした．
もぐらを叩くには，もぐらの出現位置に手を動かした後，もぐらの出てくるタイミングにぴったり合わせてもぐらを叩かなければならない．もぐらをうまく叩けると，そのもぐらに応じてポイントを得ることが出来る．もぐらを叩く動作は一瞬で行うことが出来るが，手を移動させる速さには限界がある．うさぎはもぐらを叩くにあたって左右両方の手を用いることができる．左手と右手は独立に動かすことが可能であるが，左手は常に右手より座標が小さい位置に存在しなければならない．このような条件下で，最大でどれだけのポイントが得られるかを調べたい．
Input
N
V
X
Left
X
Right
X
1
T
1
P
1
...
X
N
T
N
P
N
N
は出てくるもぐらの数，
V
は手を移動させられる最大の速さ，
X
Left
,
X
Right
はそれぞれ，左手，右手の初期位置の座標である．
X
i
,
T
i
,
P
i
はそれぞれ，
i
番目のもぐらの，出現する位置の座標，ゲーム開始から出現までの時間，叩けた際に得られるポイントである．
1 ≤
N
≤ 3,000，1 ≤
V
≤ 10,000，1 ≤
X
Left
<
X
Right
≤ 100,000，1 ≤
X
1
≤
X
2
≤ ... ≤
X
N
≤ 100,000，1 ≤
T
i
≤ 100,000，1 ≤
P
i
≤ 100,000 を満たす．(
X
i
,
T
i
) として同一の組は複数回現れない．
Output
うさぎが得られる最大のポイントを 1 行に出力せよ．
Sample Input 1
3 10 150 250
100 20 123
201 10 67
202 10 45
Sample Output 1
190
Sample Input 2
1 7 20 90
55 5 73
Sample Output 2
73
Sample Input 3
10 2 1000 2000
400 300 1
600 200 1
700 800 1
700 500 1
900 600 1
1000 700 1
1300 900 1
1400 400 1
1500 1000 1
2000 100 1
Sample Output 3
10

Submitted solutions:

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <set>
using namespace std;
typedef long long ll;
#define rep(i, n) for(int i = 0; i < (n); i++)

template<class T>
using vi = vector<T>;

template<class T>
using vii = vector<vi<T>>;

template<class T>
using viii = vector<vii<T>>;


template<class T>
struct MCF {
private:
    const T inf = 1e9;
    vector<T> dist;       //最短距離(費用)
    vector<int> pv, pe;     //直前の頂点、辺    

public:
    struct edge {
        int to, rev; int cap; T cost;
        edge(int t = 0, int r = 0, int ca = 0, T co = 0)
            : to(t), rev(r), cap(ca), cost(co) {}
    };

    struct pii {
        T d; int v; //最短距離(費用)、頂点番号
        pii(T d_ = 0, int v_ = 0) : d(d_), v(v_) {}

        bool operator<(const pii& other) const {
            if (d != other.d) return d < other.d;
            return v < other.v;
        }

        bool operator>(const pii& other) const {
            if (d != other.d) return d > other.d;
            return v > other.v;
        }
    };

    int n;
    vector<vector<edge>> to;
    vector<T> pot;        //ポテンシャル

    MCF(int n_ = 1) : n(n_), to(n_), pot(n_), dist(n_), pv(n_), pe(n_) {}

    void addedge(int u, int v, int cap, T cost) {
        int su = (int)to[u].size();
        int sv = (int)to[v].size();
        to[u].push_back({ v, sv, cap, cost });
        to[v].push_back({ u, su, 0, -cost });
    }

    bool bellmanford(int s, int t) {
        dist.assign(n, inf);
        dist[s] = 0;
        int cnt = 0;
        while (cnt < n) {
            bool end = true;
            for (int v = 0; v < n; v++) {
                if (dist[v] == inf) continue;
                for (auto e : to[v]) {
                    if (e.cap == 0) continue;
                    if (dist[v] + e.cost < dist[e.to]) {
                        dist[e.to] = dist[v] + e.cost;
                        end = false;
                    }
                }
            }
            cerr << cnt << " ";

            if (end) break;
            cnt++;
        }

        for (int v = 0; v < n; v++) pot[v] += dist[v];

        return (cnt == n);
    }

    //s->tへ流量fの最小費用流、流せないときは-1
    T mincostflow(int s, int t, int f) {
        T res = 0;
        pot.assign(n, 0);
        bellmanford(s, t);
        while (f) {
            priority_queue<pii, vector<pii>, greater<pii>> pq;
            dist.assign(n, inf);
            dist[s] = 0;
            pq.push({ 0, s });
            while (!pq.empty()) {
                pii elem = pq.top();
                pq.pop();
                if (dist[elem.v] < elem.d) continue;
                int sv = (int)to[elem.v].size();
                for (int i = 0; i < sv; i++) {
                    edge& nv = to[elem.v][i];
                    if (nv.cap == 0 || dist[nv.to] + pot[nv.to] <= dist[elem.v] + pot[elem.v] + nv.cost) continue;
                    dist[nv.to] = dist[elem.v] + pot[elem.v] - pot[nv.to] + nv.cost;
                    pv[nv.to] = elem.v;
                    pe[nv.to] = i;
                    pq.push({ dist[nv.to], nv.to });
                }
            }

            if (dist[t] == inf) return -1; //流せる最小費用流が存在しない

            for (int v = 0; v < n; v++) pot[v] += dist[v];

            int nf = f;
            for (int v = t; v != s; v = pv[v]) nf = min(nf, to[pv[v]][pe[v]].cap);
            f -= nf;
            res += nf * (pot[t] - pot[s]); //pot[s] = 0で不要だがポテンシャルを明確化する
            for (int v = t; v != s; v = pv[v]) {
                edge& nv = to[pv[v]][pe[v]];
                nv.cap -= nf;
                to[v][nv.rev].cap += nf;
            }
        }
        return res;
    }

    //s->tへ流量fの最小費用流、流せないときは費用と流せなかった流量のペア
    pair<T, int> mincostflow_pair(int s, int t, int f) {
        T res = 0;
        pot.assign(n, 0);
        while (f) {
            priority_queue<pii, vector<pii>, greater<pii>> pq;
            dist.assign(n, inf);
            dist[s] = 0;
            pq.push({ 0, s });
            while (!pq.empty()) {
                pii elem = pq.top();
                pq.pop();
                if (dist[elem.v] < elem.d) continue;
                int sv = (int)to[elem.v].size();
                for (int i = 0; i < sv; i++) {
                    edge& nv = to[elem.v][i];
                    if (nv.cap == 0 || dist[nv.to] + pot[nv.to] <= dist[elem.v] + pot[elem.v] + nv.cost) continue;
                    dist[nv.to] = dist[elem.v] + pot[elem.v] - pot[nv.to] + nv.cost;
                    pv[nv.to] = elem.v;
                    pe[nv.to] = i;
                    pq.push({ dist[nv.to], nv.to });
                }
            }

            if (dist[t] == inf) return { res, f }; //流せる最小費用流が存在しない

            for (int v = 0; v < n; v++) pot[v] += dist[v];

            long long nf = f;
            for (int v = t; v != s; v = pv[v]) nf = min(nf, to[pv[v]][pe[v]].cap);
            f -= nf;
            res += nf * (pot[t] - pot[s]); //pot[s] = 0で不要だがポテンシャルを明確化する
            for (int v = t; v != s; v = pv[v]) {
                edge& nv = to[pv[v]][pe[v]];
                nv.cap -= nf;
                to[v][nv.rev].cap += nf;
            }
        }
        return { res, f };
    }
};

vi<int> x(3010), t(3010), p(3010);
vi<tuple<int, int, int>> xtp(3010, { 1e9, 1e9, 1e9 });
MCF<int> mcf(6020);

int main()
{
    int n; ll v, xl, xr;
    cin >> n >> v >> xl >> xr;
    rep(i, n) cin >> x[i] >> t[i] >> p[i];
    rep(i, n) xtp[i] = { t[i], x[i], p[i] };
    sort(xtp.begin(), xtp.end());
    rep(i, n) {
        t[i] = get<0>(xtp[i]);
        x[i] = get<1>(xtp[i]);
        p[i] = get<2>(xtp[i]);
    }

    int S = 0, S1 = 1, S2 = 2, T = 2 * n + 3;

    mcf.addedge(S, S1, 1, 0);
    mcf.addedge(S, S2, 1, 0);

    rep(_, 2) {
        rep(i, n) {
            ll dx = abs(x[i] - xl);
            ll dt = t[i];
            if (dx <= dt * v) mcf.addedge(S1, 2 * i + 3, 1, -p[i]);
        }
        swap(xl, xr);
        swap(S1, S2);
    }

    rep(i, n) {
        mcf.addedge(2 * i + 3, 2 * i + 4, 1, 0);
        rep(j, n) {
            if (i == j) continue;
            if (t[i] > t[j]) continue;
            ll dx = abs(x[j] - x[i]);
            ll dt = t[j] - t[i];
            if (dx <= dt * v) mcf.addedge(2 * i + 4, 2 * j + 3, 1, -p[j]);
        }
        mcf.addedge(2 * i + 4, T, 1, 0);
    }

    mcf.addedge(S1, T, 1, 0);
    mcf.addedge(S2, T, 1, 0);

    ll ans = mcf.mincostflow(S, T, 2);
    cout << -ans << endl;

    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 242836
final_rank: 3

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <set>
using namespace std;
typedef long long ll;
#define rep(i, n) for(int i = 0; i < (n); i++)

template<class T>
using vi = vector<T>;

template<class T>
using vii = vector<vi<T>>;

template<class T>
using viii = vector<vii<T>>;


template<class T>
struct MCF {
private:
    const T inf = 1e9;
    vector<T> dist;       //最短距離(費用)
    vector<int> pv, pe;     //直前の頂点、辺    

public:
    struct edge {
        int to, rev; int cap; T cost;
        edge(int t = 0, int r = 0, int ca = 0, T co = 0)
            : to(t), rev(r), cap(ca), cost(co) {}
    };

    struct pii {
        T d; int v; //最短距離(費用)、頂点番号
        pii(T d_ = 0, int v_ = 0) : d(d_), v(v_) {}

        bool operator<(const pii& other) const {
            if (d != other.d) return d < other.d;
            return v < other.v;
        }

        bool operator>(const pii& other) const {
            if (d != other.d) return d > other.d;
            return v > other.v;
        }
    };

    int n;
    vector<vector<edge>> to;
    vector<T> pot;        //ポテンシャル

    MCF(int n_ = 1) : n(n_), to(n_), pot(n_), dist(n_), pv(n_), pe(n_) {}

    void addedge(int u, int v, int cap, T cost) {
        int su = (int)to[u].size();
        int sv = (int)to[v].size();
        to[u].push_back({ v, sv, cap, cost });
        to[v].push_back({ u, su, 0, -cost });
    }

    bool bellmanford(int s, int t) {
        dist.assign(n, inf);
        dist[s] = 0;
        int cnt = 0;
        while (cnt < n) {
            bool end = true;
            for (int v = 0; v < n; v++) {
                if (dist[v] == inf) continue;
                for (auto e : to[v]) {
                    if (e.cap == 0) continue;
                    if (dist[v] + e.cost < dist[e.to]) {
                        dist[e.to] = dist[v] + e.cost;
                        end = false;
                    }
                }
            }
            //cerr << cnt << " ";

            if (end) break;
            cnt++;
        }

        for (int v = 0; v < n; v++) pot[v] += dist[v];

        return (cnt == n);
    }

    //s->tへ流量fの最小費用流、流せないときは-1
    T mincostflow(int s, int t, int f) {
        T res = 0;
        pot.assign(n, 0);
        bellmanford(s, t);
        while (f) {
            priority_queue<pii, vector<pii>, greater<pii>> pq;
            dist.assign(n, inf);
            dist[s] = 0;
            pq.push({ 0, s });
            while (!pq.empty()) {
                pii elem = pq.top();
                pq.pop();
                if (dist[elem.v] < elem.d) continue;
                int sv = (int)to[elem.v].size();
                for (int i = 0; i < sv; i++) {
                    edge& nv = to[elem.v][i];
                    if (nv.cap == 0 || dist[nv.to] + pot[nv.to] <= dist[elem.v] + pot[elem.v] + nv.cost) continue;
                    dist[nv.to] = dist[elem.v] + pot[elem.v] - pot[nv.to] + nv.cost;
                    pv[nv.to] = elem.v;
                    pe[nv.to] = i;
                    pq.push({ dist[nv.to], nv.to });
                }
            }

            if (dist[t] == inf) return -1; //流せる最小費用流が存在しない

            for (int v = 0; v < n; v++) pot[v] += dist[v];

            int nf = f;
            for (int v = t; v != s; v = pv[v]) nf = min(nf, to[pv[v]][pe[v]].cap);
            f -= nf;
            res += nf * (pot[t] - pot[s]); //pot[s] = 0で不要だがポテンシャルを明確化する
            for (int v = t; v != s; v = pv[v]) {
                edge& nv = to[pv[v]][pe[v]];
                nv.cap -= nf;
                to[v][nv.rev].cap += nf;
            }
        }
        return res;
    }

    //s->tへ流量fの最小費用流、流せないときは費用と流せなかった流量のペア
    pair<T, int> mincostflow_pair(int s, int t, int f) {
        T res = 0;
        pot.assign(n, 0);
        while (f) {
            priority_queue<pii, vector<pii>, greater<pii>> pq;
            dist.assign(n, inf);
            dist[s] = 0;
            pq.push({ 0, s });
            while (!pq.empty()) {
                pii elem = pq.top();
                pq.pop();
                if (dist[elem.v] < elem.d) continue;
                int sv = (int)to[elem.v].size();
                for (int i = 0; i < sv; i++) {
                    edge& nv = to[elem.v][i];
                    if (nv.cap == 0 || dist[nv.to] + pot[nv.to] <= dist[elem.v] + pot[elem.v] + nv.cost) continue;
                    dist[nv.to] = dist[elem.v] + pot[elem.v] - pot[nv.to] + nv.cost;
                    pv[nv.to] = elem.v;
                    pe[nv.to] = i;
                    pq.push({ dist[nv.to], nv.to });
                }
            }

            if (dist[t] == inf) return { res, f }; //流せる最小費用流が存在しない

            for (int v = 0; v < n; v++) pot[v] += dist[v];

            long long nf = f;
            for (int v = t; v != s; v = pv[v]) nf = min(nf, to[pv[v]][pe[v]].cap);
            f -= nf;
            res += nf * (pot[t] - pot[s]); //pot[s] = 0で不要だがポテンシャルを明確化する
            for (int v = t; v != s; v = pv[v]) {
                edge& nv = to[pv[v]][pe[v]];
                nv.cap -= nf;
                to[v][nv.rev].cap += nf;
            }
        }
        return { res, f };
    }
};

vi<int> x(3010), t(3010), p(3010);
vi<tuple<int, int, int>> xtp(3010, { 1e9, 1e9, 1e9 });
MCF<int> mcf(6020);

int main()
{
    int n; ll v, xl, xr;
    cin >> n >> v >> xl >> xr;
    rep(i, n) cin >> x[i] >> t[i] >> p[i];
    rep(i, n) xtp[i] = { t[i], x[i], p[i] };
    sort(xtp.begin(), xtp.end());
    rep(i, n) {
        t[i] = get<0>(xtp[i]);
        x[i] = get<1>(xtp[i]);
        p[i] = get<2>(xtp[i]);
    }

    int S = 0, S1 = 1, S2 = 2, T = 2 * n + 3;

    mcf.addedge(S, S1, 1, 0);
    mcf.addedge(S, S2, 1, 0);

    rep(_, 2) {
        rep(i, n) {
            ll dx = abs(x[i] - xl);
            ll dt = t[i];
            if (dx <= dt * v) mcf.addedge(S1, 2 * i + 3, 1, -p[i]);
        }
        swap(xl, xr);
        swap(S1, S2);
    }

    rep(i, n) {
        mcf.addedge(2 * i + 3, 2 * i + 4, 1, 0);
        rep(j, n) {
            if (i == j) continue;
            if (t[i] > t[j]) continue;
            ll dx = abs(x[j] - x[i]);
            ll dt = t[j] - t[i];
            if (dx <= dt * v) mcf.addedge(2 * i + 4, 2 * j + 3, 1, -p[j]);
        }
        mcf.addedge(2 * i + 4, T, 1, 0);
    }

    mcf.addedge(S1, T, 1, 0);
    mcf.addedge(S2, T, 1, 0);

    ll ans = mcf.mincostflow(S, T, 2);
    cout << -ans << endl;

    return 0;
}
accuracy: 1
time_ms: 920
memory_kb: 243460
final_rank: 9

code_snippet: #line 1 "main.cpp"
#include <bits/stdc++.h>
// #include "Utils/FastIO.hpp"
#line 7 "/home/kokoro601/compro_library/Flow/MinCostFlow.hpp"

// this implementation is based on
// https://megalodon.jp/2022-0321-1006-53/https://ei1333.hateblo.jp:443/entry/2019/12/15/094229
// verify:
// https://atcoder.jp/contests/practice2/submissions/30316518
// https://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=6331152

template<class CapType, class CostType> class MinCostFlow {
    struct Edge {
        int to, rev;
        CapType cap;
        CostType cost;
    };

    struct EdgeInfo {
        int v, offset;
    };

    using P = std::pair<CostType, int>;

    int n;
    const CostType inf;
    std::vector<CostType> h, dist;
    std::vector<int> prevv, preve;
    std::vector<CapType> b;
    std::vector<EdgeInfo> edge_infos;
    CostType res = 0;

public:
    std::vector< std::vector<Edge> > g;

    MinCostFlow(int node_size) : 
        n(node_size), inf(std::numeric_limits<CostType>::max()),
        g(n), h(n, 0), dist(n), prevv(n), preve(n), b(n) {}

    CostType solve(int s, int t, CapType f) {
        while(f > 0) {
            std::priority_queue<P, std::vector<P>, std::greater<P> > que;
            std::fill(dist.begin(), dist.end(), inf);
            dist[s] = 0;
            que.push({0, s});
            while(!que.empty()) {
                P p = que.top(); que.pop();
                int v = p.second;
                if (dist[v] < p.first) continue;
                for (int i = 0; i < (int)g[v].size(); i++) {
                    Edge &e = g[v][i];
                    CostType diff = e.cost + h[v] - h[e.to];
                    if (e.cap > 0 && dist[e.to] > dist[v] + diff) {
                        dist[e.to] = dist[v] + diff;
                        prevv[e.to] = v, preve[e.to] = i;
                        que.push({dist[e.to], e.to});
                    }
                }
            }

            if (dist[t] == inf) {
                std::cout << "-1" << std::endl;
                exit(0);
            }

            for (int i = 0; i < n; i++) h[i] += dist[i];

            CapType d = f;
            for (int v = t; v != s; v = prevv[v]) {
                d = std::min(d, g[prevv[v]][preve[v]].cap);
            }

            f -= d;
            res += h[t] * d;
            for (int v = t; v != s; v = prevv[v]) {
                Edge& e = g[prevv[v]][preve[v]];
                e.cap -= d;
                g[v][e.rev].cap += d;
            }
        }

        return res;
    }

    void set_potential(std::vector<CostType> &potential) {
        h = potential;
    }

    void add_edge(int from, int to, CapType cap, CostType cost) {
        assert(from != to); 
        g[from].push_back({to, (int)g[to].size(), cap, cost});
        g[to].push_back({from, (int)g[from].size() - 1, 0, -cost});
        edge_infos.push_back({to, (int)g[to].size() - 1});
    }

    CapType get_edge(int i) {
        EdgeInfo &ei = edge_infos[i];
        Edge &e = g[ei.v][ei.offset];
        CapType ret = e.cap;
        return ret;
    }
};
#line 4 "/home/kokoro601/compro_library/Graph/SCC.hpp"

// verify:
// https://judge.yosupo.jp/submission/83473
// https://atcoder.jp/contests/arc010/submissions/30376565


class SCC {
    using Graph = std::vector< std::vector<int> >;

    void dfs(int v) {
        used[v] = true;
        for (auto &to: g[v]) {
            if (!used[to]) dfs(to);
        }
        ord.push_back(v);
    }

    void rdfs(int v, int group_id) {
        used[v] = true;
        cmp[v] = group_id;
        for (auto &to: rg[v]) {
            if (!used[to]) rdfs(to, group_id);
        }
    }

    void build() {
        for (int v = 0; v < n; v++)
            if (!used[v]) dfs(v);

        std::fill(used.begin(), used.end(), 0);

        std::reverse(ord.begin(), ord.end());
        for (auto &v: ord)
            if (!used[v]) rdfs(v, n_group++);
    }

    int n;
    Graph g, rg;
    std::vector<bool> used;
    std::vector<int> ord;
public:
    int n_group;
    std::vector<int> cmp;

    SCC(Graph &g): n((int)g.size()), g(g), used(n), n_group(0), cmp(n){
        rg.resize(n);
        for (int i = 0; i < n; i++)
            for (auto to: g[i]) 
                rg[to].push_back(i);
        build();
    }

    std::vector< std::vector<int> > make_group_list() {
        std::vector< std::vector<int> > group_list(n_group);
        for (int i = 0; i < n; i++) group_list[cmp[i]].push_back(i);
        return group_list;
    }

    Graph rebuild() {
        Graph ret_g(n_group);
        auto group_list = make_group_list();

        std::vector<bool> marked_fl(n_group, false);
        for (int i = 0; i < n_group; i++) {
            std::vector<int> rec_marked_group;
            for (auto &v: group_list[i]) {
                for (auto &to: g[v]) {
                    int to_group_id = cmp[to];
                    if (to_group_id != i && !marked_fl[to_group_id]) {
                        marked_fl[to_group_id] = true;
                        rec_marked_group.push_back(to_group_id);
                        ret_g[i].push_back(to_group_id);
                    }
                }
            }
            for (auto &group_id: rec_marked_group) marked_fl[group_id] = false;
        }

        return ret_g;
    }
};
#line 5 "main.cpp"

using namespace std;
using ull = unsigned long long;
using ll = long long;
using Graph = vector<vector<int>>;
// using u128 = __uint128_t;   
using u64 = uint64_t;


// vector<Mint> inv(vector<Mint> &v) {
//     size_t n = v.size();

//     vector<Mint> ret = { modpow(v[0].v, MOD-2, MOD) };
//     vector<Mint> cur = { v[0] }; 
//     size_t cursz = 1;
//     while (cursz < n) {
//         cur.resize(2*cursz); memcpy(cur.data() + cursz, v.data() + cursz, sizeof(unsigned int) * min(n-cursz, cursz));
//         auto tmp = ntt.convolution(cur, ret);
//         tmp[0] = Mint(2) - tmp[0];
//         for (int i = 1; i < tmp.size(); i++) tmp[i] *= -1;
//         tmp.resize(2*cursz);
//         ret = ntt.convolution(ret, tmp);
//         ret.resize(2*cursz);
//         cursz *= 2;
//     }

//     ret.resize(n);
//     return ret;
// }

typedef struct {
    int x, t, p;
} Item;

int main() {
    int n, v; cin >> n >> v;
    int xleft, xright; cin >> xleft >> xright;

    vector<Item> items(n);
    for (int i = 0; i < n; i++) cin >> items[i].x >> items[i].t >> items[i].p;

    // 時間でソート
    sort(items.begin(), items.end(), [](auto &a, auto &b) { return a.t < b.t; }); 

    int s = 2*n, t = 2*n + 1;
    MinCostFlow<int, int> mcf(2*n + 2);
    mcf.add_edge(s, t, 2, 0);
    for (int i = 0; i < n; i++) { // s ⇒ 各頂点
        if (abs(xleft - items[i].x) <= items[i].t * v)
            mcf.add_edge(s, i, 1, 0);
        if (abs(xright - items[i].x) <= items[i].t * v)
            mcf.add_edge(s, i, 1, 0);
    }
    for (int i = 0; i < n; i++) // 各頂点 ⇒ t
        mcf.add_edge(i+n, t, 1, 0);
    for (int i = 0; i < n; i++)
        mcf.add_edge(i, i+n, 1, -items[i].p); // ポイント
    
    for (int i = 0; i < n; i++) 
        for (int j = i+1; j < n; j++) 
            if (abs(items[i].x - items[j].x) <= v * (items[j].t - items[i].t))
                mcf.add_edge(i+n, j, 1, 0);

    vector<int> potential(2*n + 2, 1e9);
    potential[s] = 0;
    for (auto e: mcf.g[s])
        if (e.cap != 0)
            potential[e.to] = min(potential[e.to], potential[s] + e.cost); 
    for (int i = 0; i < n; i++) {
        for (auto e: mcf.g[i]) 
            if (e.cap != 0)
                potential[e.to] = min(potential[e.to], potential[i] + e.cost);
        for (auto e: mcf.g[i+n]) 
            if (e.cap != 0)
                potential[e.to] = min(potential[e.to], potential[i+n] + e.cost);
    }

    mcf.set_potential(potential);

    cout << -mcf.solve(s, t, 2) << "\n";
}
accuracy: 0.2653061224489796
time_ms: 110
memory_kb: 120300
final_rank: 19

code_snippet: #line 1 "main.cpp"
#include <iostream>
#include <algorithm>
#include <vector>
#include <iomanip>
#include <math.h>
#include <functional>
#include <map>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <stack>
#include <cstring>
#include <assert.h>
#include <unistd.h>
#include <chrono>
#include <numeric>
#include <cstdint>
#include <variant>
#include <random>
#include <memory>
// #include <bit>
// #include "Utils/FastIO.hpp"
#line 5 "/home/kokoro601/compro_library/Flow/MinCostFlow.hpp"
#include <limits>
#line 7 "/home/kokoro601/compro_library/Flow/MinCostFlow.hpp"

// this implementation is based on
// https://megalodon.jp/2022-0321-1006-53/https://ei1333.hateblo.jp:443/entry/2019/12/15/094229
// verify:
// https://atcoder.jp/contests/practice2/submissions/30316518
// https://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=6331152




template<class CapType, class CostType> class MinCostFlow {
    struct Edge {
        int to, rev;
        CapType cap;
        CostType cost;
    };

    struct EdgeInfo {
        int v, offset;
    };

    using P = std::pair<CostType, int>;

    int n;
    const CostType inf;
    std::vector<CostType> h, dist;
    std::vector<int> prevv, preve;
    std::vector<CapType> b;
    std::vector<EdgeInfo> edge_infos;
    CostType res = 0;

public:
    // std::vector< std::vector<Edge> > g;
    Edge *g[7000];
    short hi[7000] = {}, lim[7000] = {};

    MinCostFlow(int node_size) : 
        n(node_size), inf(std::numeric_limits<CostType>::max()),
        h(n, 0), dist(n), prevv(n), preve(n), b(n) {}

    CostType solve(int s, int t, CapType f) {
        while(f > 0) {
            std::priority_queue<P, std::vector<P>, std::greater<P> > que;
            std::fill(dist.begin(), dist.end(), inf);
            dist[s] = 0;
            que.push({0, s});
            while(!que.empty()) {
                P p = que.top(); que.pop();
                int v = p.second;
                if (dist[v] < p.first) continue;
                for (int i = 0; i < (int)hi[v]; i++) {
                    Edge &e = g[v][i];
                    CostType diff = e.cost + h[v] - h[e.to];
                    if (e.cap > 0 && dist[e.to] > dist[v] + diff) {
                        dist[e.to] = dist[v] + diff;
                        prevv[e.to] = v, preve[e.to] = i;
                        que.push({dist[e.to], e.to});
                    }
                }
            }

            if (dist[t] == inf) {
                std::cout << "-1" << std::endl;
                exit(0);
            }

            for (int i = 0; i < n; i++) h[i] += dist[i];

            CapType d = f;
            for (int v = t; v != s; v = prevv[v]) {
                d = std::min(d, g[prevv[v]][preve[v]].cap);
            }

            f -= d;
            res += h[t] * d;
            for (int v = t; v != s; v = prevv[v]) {
                Edge& e = g[prevv[v]][preve[v]];
                e.cap -= d;
                g[v][e.rev].cap += d;
            }
        }

        return res;
    }

    void set_potential(std::vector<CostType> &potential) {
        h = potential;
    }

    void add_edge(int from, int to, CapType cap, CostType cost) {
        assert(from != to); 

        if (lim[from] == hi[from]) {
            lim[from] += 8;
            g[from] = (Edge*)realloc(g[from], sizeof(Edge) * lim[from]);
        }
        if (lim[to] == hi[to]) {
            lim[to] += 8;
            g[to] = (Edge*)realloc(g[to], sizeof(Edge) * lim[to]);
        }

        g[from][hi[from]++] = {to, (int)hi[to], cap, cost};
        g[to][hi[to]++] = {from, (int)hi[from] - 1, 0, -cost};
        // edge_infos.push_back({to, (int)g[to].size() - 1});
    }

    CapType get_edge(int i) {
        EdgeInfo &ei = edge_infos[i];
        Edge &e = g[ei.v][ei.offset];
        CapType ret = e.cap;
        return ret;
    }
};
#line 26 "main.cpp"

using namespace std;
using ull = unsigned long long;
using ll = long long;
using Graph = vector<vector<int>>;
using u128 = __uint128_t;   
using u64 = uint64_t;

// 番兵は入っているとする
// ll garner(vector<ll> &b, vector<ll> &m) {
//     vector<ll> coeffs(m.size(), 1);
//     vector<ll> constants(m.size(), 0);
//     for (size_t k = 0; k < b.size(); k++) {
//         ll diff = (b[k] > constants[k]) ? (b[k] - constants[k]) : (b[k] - constants[k] + m[k]);
//         ll t = (diff * modinv(coeffs[k], m[k])) % m[k];
//         for (size_t i = k + 1; i < m.size(); i++) {
//             (constants[i] += t * coeffs[i]) %= m[i];
//             (coeffs[i] *= m[k]) %= m[i];
//         }
//     }

//     return constants.back();
// }

struct Item {
    int x, t, p;
};

int main() {
    int n, v, xl, xr;
    cin >> n >> v >> xl >> xr;
    vector<Item> items(n);
    for (int i = 0; i < n; i++) cin >> items[i].x >> items[i].t >> items[i].p;
    items.push_back({xl, 0, 0});
    items.push_back({xr, 0, 0});
    // 時間でソート
    sort(items.begin(), items.end(), [](auto &a, auto &b) { return a.t < b.t; });

    n += 2;

    MinCostFlow<int, int> mcf(2*n+2);
    int s = 2*n, t = 2*n+1;
    mcf.add_edge(s, 0, 1, 0), mcf.add_edge(s, 1, 1, 0);
    for (int i = 0; i < n; i++) mcf.add_edge(i, i+n, 1, -items[i].p);
    for (int i = 0; i < n; i++) mcf.add_edge(i+n, t, 1, 0);
    for (int i = 0; i < n; i++) {
        for (int j = i+1; j < n; j++) {
            // 到達可能
            if (abs(items[i].x - items[j].x) <= v * (items[j].t - items[i].t)) {
                mcf.add_edge(i+n, j, 1, 0);
            }
        }
    }

    vector<int> potential(2*n+2, 1e9), top(2*n+2);
    top[0] = s;
    for (int i = 0; i < n; i++) top[2*i + 1] = i, top[2*i + 2] = i+n; 
    top[2*n+1] = t;

    potential[s] = 0;
    for (auto cur: top) {
        for (int i = 0; i < mcf.hi[cur]; i++) {
            auto e = mcf.g[cur][i];
            if (e.cap == 0) continue;
            potential[e.to] = min(potential[e.to], potential[cur] + e.cost);
        }
    }

    mcf.set_potential(potential);

    cout << -mcf.solve(s, t, 2) << "\n";
}
accuracy: 1
time_ms: 1050
memory_kb: 240792
final_rank: 13

code_snippet: #line 1 "main.cpp"
#include <iostream>
#include <algorithm>
#include <vector>
#include <iomanip>
#include <math.h>
#include <functional>
#include <map>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <stack>
#include <cstring>
#include <assert.h>
#include <unistd.h>
#include <chrono>
#include <numeric>
#include <cstdint>
#include <variant>
#include <random>
#include <memory>
// #include <bit>
// #include "Utils/FastIO.hpp"
#line 5 "/home/kokoro601/compro_library/Flow/MinCostFlow.hpp"
#include <limits>
#line 7 "/home/kokoro601/compro_library/Flow/MinCostFlow.hpp"

// this implementation is based on
// https://megalodon.jp/2022-0321-1006-53/https://ei1333.hateblo.jp:443/entry/2019/12/15/094229
// verify:
// https://atcoder.jp/contests/practice2/submissions/30316518
// https://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=6331152




template<class CapType, class CostType> class MinCostFlow {
    struct Edge {
        int to, rev;
        CapType cap;
        CostType cost;
    };

    struct EdgeInfo {
        int v, offset;
    };

    using P = std::pair<CostType, int>;

    int n;
    const CostType inf;
    std::vector<CostType> h, dist;
    std::vector<int> prevv, preve;
    std::vector<CapType> b;
    std::vector<EdgeInfo> edge_infos;
    CostType res = 0;

public:
    // std::vector< std::vector<Edge> > g;
    Edge *g[7000];
    int hi[7000] = {}, lim[7000] = {};

    MinCostFlow(int node_size) : 
        n(node_size), inf(std::numeric_limits<CostType>::max()),
        h(n, 0), dist(n), prevv(n), preve(n), b(n) {}

    CostType solve(int s, int t, CapType f) {
        while(f > 0) {
            std::priority_queue<P, std::vector<P>, std::greater<P> > que;
            std::fill(dist.begin(), dist.end(), inf);
            dist[s] = 0;
            que.push({0, s});
            while(!que.empty()) {
                P p = que.top(); que.pop();
                int v = p.second;
                if (dist[v] < p.first) continue;
                for (int i = 0; i < (int)hi[v]; i++) {
                    Edge &e = g[v][i];
                    CostType diff = e.cost + h[v] - h[e.to];
                    if (e.cap > 0 && dist[e.to] > dist[v] + diff) {
                        dist[e.to] = dist[v] + diff;
                        prevv[e.to] = v, preve[e.to] = i;
                        que.push({dist[e.to], e.to});
                    }
                }
            }

            if (dist[t] == inf) {
                std::cout << "-1" << std::endl;
                exit(0);
            }

            for (int i = 0; i < n; i++) h[i] += dist[i];

            CapType d = f;
            for (int v = t; v != s; v = prevv[v]) {
                d = std::min(d, g[prevv[v]][preve[v]].cap);
            }

            f -= d;
            res += h[t] * d;
            for (int v = t; v != s; v = prevv[v]) {
                Edge& e = g[prevv[v]][preve[v]];
                e.cap -= d;
                g[v][e.rev].cap += d;
            }
        }

        return res;
    }

    void set_potential(std::vector<CostType> &potential) {
        h = potential;
    }

    void add_edge(int from, int to, CapType cap, CostType cost) {
        assert(from != to); 

        if (lim[from] == hi[from]) {
            lim[from] += 8;
            g[from] = (Edge*)realloc(g[from], sizeof(Edge) * lim[from]);
        }
        if (lim[to] == hi[to]) {
            lim[to] += 8;
            g[to] = (Edge*)realloc(g[to], sizeof(Edge) * lim[to]);
        }

        g[from][hi[from]++] = {to, (int)hi[to], cap, cost};
        g[to][hi[to]++] = {from, (int)hi[from] - 1, 0, -cost};
        // edge_infos.push_back({to, (int)g[to].size() - 1});
    }

    CapType get_edge(int i) {
        EdgeInfo &ei = edge_infos[i];
        Edge &e = g[ei.v][ei.offset];
        CapType ret = e.cap;
        return ret;
    }
};
#line 26 "main.cpp"

using namespace std;
using ull = unsigned long long;
using ll = long long;
using Graph = vector<vector<int>>;
using u128 = __uint128_t;   
using u64 = uint64_t;

// 番兵は入っているとする
// ll garner(vector<ll> &b, vector<ll> &m) {
//     vector<ll> coeffs(m.size(), 1);
//     vector<ll> constants(m.size(), 0);
//     for (size_t k = 0; k < b.size(); k++) {
//         ll diff = (b[k] > constants[k]) ? (b[k] - constants[k]) : (b[k] - constants[k] + m[k]);
//         ll t = (diff * modinv(coeffs[k], m[k])) % m[k];
//         for (size_t i = k + 1; i < m.size(); i++) {
//             (constants[i] += t * coeffs[i]) %= m[i];
//             (coeffs[i] *= m[k]) %= m[i];
//         }
//     }

//     return constants.back();
// }

struct Item {
    int x, t, p;
};

int main() {
    int n, v, xl, xr;
    cin >> n >> v >> xl >> xr;
    vector<Item> items(n);
    for (int i = 0; i < n; i++) cin >> items[i].x >> items[i].t >> items[i].p;
    items.push_back({xl, 0, 0});
    items.push_back({xr, 0, 0});
    // 時間でソート
    sort(items.begin(), items.end(), [](auto &a, auto &b) { return a.t < b.t; });

    n += 2;

    MinCostFlow<int, int> mcf(2*n+2);
    int s = 2*n, t = 2*n+1;
    mcf.add_edge(s, 0, 1, 0), mcf.add_edge(s, 1, 1, 0);
    for (int i = 0; i < n; i++) mcf.add_edge(i, i+n, 1, -items[i].p);
    for (int i = 0; i < n; i++) mcf.add_edge(i+n, t, 1, 0);
    for (int i = 0; i < n; i++) {
        for (int j = i+1; j < n; j++) {
            // 到達可能
            if (abs(items[i].x - items[j].x) <= v * (items[j].t - items[i].t)) {
                mcf.add_edge(i+n, j, 1, 0);
            }
        }
    }

    vector<int> potential(2*n+2, 1e9), top(2*n+2);
    top[0] = s;
    for (int i = 0; i < n; i++) top[2*i + 1] = i, top[2*i + 2] = i+n; 
    top[2*n+1] = t;

    potential[s] = 0;
    for (auto cur: top) {
        for (int i = 0; i < mcf.hi[cur]; i++) {
            auto e = mcf.g[cur][i];
            if (e.cap == 0) continue;
            potential[e.to] = min(potential[e.to], potential[cur] + e.cost);
        }
    }

    mcf.set_potential(potential);

    cout << -mcf.solve(s, t, 2) << "\n";
}
accuracy: 1
time_ms: 1070
memory_kb: 241564
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int INF = 1012345678;

int mincostflow(int N, int S, int T, int F, vector<vector<char> >& cap, vector<vector<int> >& cost) {
	int ans = 0;
	vector<int> height(N, 0); // potential
	for (int rep = 0; rep < F; rep++) {
		vector<int> dist(N, INF);
		vector<int> pre(N, -1);
		vector<bool> vis(N, false);
		dist[S] = 0;
		while (true) {
			int pos = -1;
			for (int i = 0; i < N; i++) {
				if (!vis[i] && dist[i] != INF && (pos == -1 || dist[pos] > dist[i])) {
					pos = i;
				}
			}
			if (pos == -1) {
				break;
			}
			vis[pos] = true;
			for (int i = 0; i < N; i++) {
				int ndist = dist[pos] + cost[pos][i] - (height[i] - height[pos]);
				if (cap[pos][i] > 0 && dist[i] > ndist) {
					dist[i] = ndist;
					pre[i] = pos;
				}
			}
		}
		if (dist[T] == INF) {
			return INF;
		}
		ans += dist[T] + height[T];
		int pos = T;
		while (pos != S) {
			int nxt = pre[pos];
			cap[nxt][pos] -= 1;
			cap[pos][nxt] += 1;
			pos = nxt;
		}
		for (int i = 0; i < N; i++) {
			if (height[i] == INF || dist[i] == INF) {
				height[i] = INF;
			}
			else {
				height[i] += dist[i];
			}
		}
	}
	return ans;
}

struct enemy {
	int x, t, p;
};

int main() {
	int N, V, XL, XR;
	cin >> N >> V >> XL >> XR;
	vector<enemy> E(N);
	for (int i = 0; i < N; i++) {
		cin >> E[i].x >> E[i].t >> E[i].p;
	}
	sort(E.begin(), E.end(), [&](const enemy& e1, const enemy& e2) {
		return e1.t < e2.t;
	});
	vector<int> ps(N + 1);
	for (int i = 0; i < N; i++) {
		ps[i + 1] = ps[i] + E[i].p;
	}
	auto psum = [&](int l, int r) -> int {
		return ps[r] - ps[l];
	};
	auto reachable = [&](int xa, int ta, int xb, int tb) -> bool {
		return (ta < tb && abs(xa - xb) <= V * (tb - ta));
	};
	vector<vector<char> > cap(N * 2 + 4, vector<char>(N * 2 + 4));
	vector<vector<int> > cost(N * 2 + 4, vector<int>(N * 2 + 4));
	auto add_edge = [&](int va, int vb, int cap_, int cost_) -> void {
		cap[va][vb] = cap_;
		cap[vb][va] = 0;
		cost[va][vb] = cost_;
		cost[vb][va] = -cost_;
	};
	for (int i = 0; i < N; i++) {
		add_edge(i, N + i, 1, 0);
	}
	for (int i = 0; i < N; i++) {
		for (int j = i + 1; j < N; j++) {
			if (reachable(E[i].x, E[i].t, E[j].x, E[j].t)) {
				add_edge(N + i, j, 1, psum(i + 1, j));
			}
		}
	}
	for (int i = 0; i < N; i++) {
		if (reachable(XL, 0, E[i].x, E[i].t)) {
			add_edge(2 * N + 0, i, 1, psum(0, i));
		}
		if (reachable(XR, 0, E[i].x, E[i].t)) {
			add_edge(2 * N + 1, i, 1, psum(0, i));
		}
		add_edge(N + i, 2 * N + 3, 1, psum(i + 1, N));
	}
	add_edge(2 * N + 2, 2 * N + 0, 1, 0);
	add_edge(2 * N + 2, 2 * N + 1, 1, 0);
	add_edge(2 * N + 0, 2 * N + 3, 1, psum(0, N));
	add_edge(2 * N + 1, 2 * N + 3, 1, psum(0, N));
	int ans = mincostflow(2 * N + 4, 2 * N + 2, 2 * N + 3, 2, cap, cost);
	cout << psum(0, N) * 2 - ans << endl;
	return 0;
}
accuracy: 1
time_ms: 290
memory_kb: 179712
final_rank: 1

code_snippet: //#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
const ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;

#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 2;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

template<typename T>
struct mcf {
private:
	struct edge {
		int to, cap; T cost; int rev;
	};
	vector<vector<edge>> G;
	vector<P> par;
	vector<T> dist;
	T inf = mod;
public:
	mcf(int n) {
		G.resize(n);
		par.resize(n);
		dist.resize(n);
	}
	void add_edge(int from, int to, int cap, T cost) {
		G[from].push_back({ to,cap,cost,(int)G[to].size() });
		G[to].push_back({ from,0,-cost,(int)G[from].size() - 1 });
	}
	pair<T, int> minimum_road(int s, int t) {
		fill(all(par), P{ -1,-1 });
		fill(all(dist), inf);
		dist[s] = 0;
		priority_queue<pair<T, int>, vector<pair<T, int>>, greater<pair<T, int>>> q;
		q.push({ 0,s });
		while (!q.empty()) {
			pair<T, int> p = q.top(); q.pop();
			int id = p.second;
			if (id == t)continue;
			if (p.first > dist[id])continue;
			rep(j, G[id].size()) {
				if (G[id][j].cap > 0) {
					int to = G[id][j].to;
					T nd = p.first + G[id][j].cost;
					if (nd < dist[to]) {
						dist[to] = nd;
						par[to] = { id,j };
						q.push({ dist[to],to });
					}
				}
			}
		}
		int cur = t;
		int f = mod;
		while (cur != s) {
			int p = par[cur].first, j = par[cur].second;
			if (p < 0)return { -1,-1 };
			f = min(f, G[p][j].cap);
			cur = p;
		}
		cur = t;
		while (cur != s) {
			int p = par[cur].first, j = par[cur].second;
			if (p < 0)return { -1,-1 };
			G[p][j].cap -= f;
			if (G[p][j].rev >= 0) {
				G[cur][G[p][j].rev].cap += f;
			}
			cur = p;
		}
		return { dist[t],f };
	}
	T minimum_cost_flow(int s, int t, int k) {
		T ret = 0;
		rep(i, k) {
			pair<T, int> z = minimum_road(s, t);
			if (z.first < 0)return -1;
			if (k - i <= z.second) {
				ret += z.first * (k - i); break;
			}
			i += z.second - 1;
			ret += z.first * z.second;
		}
		return ret;
	}
};

void solve() {
	int n, v, xl, xr; cin >> n >> v >> xl >> xr;
	vector<int> x(n), t(n), p(n);
	rep(i, n) {
		cin >> x[i] >> t[i] >> p[i];
	}

	x.push_back(xl);
	t.push_back(0);
	p.push_back(0);
	x.push_back(xr);
	t.push_back(0);
	p.push_back(0);

	n += 2;
	vector<P> vp;
	rep(i, n)vp.push_back({ t[i],i });
	sort(all(vp));
	vector<int> nx(n), nt(n), np(n);
	rep(i, n) {
		int id = vp[i].second;
		nx[i] = x[id];
		nt[i] = t[id];
		np[i] = p[id];
	}
	swap(x, nx);
	swap(t, nt);
	swap(p, np);
	vector<int> rp(n + 1);
	rep(i, n)rp[i + 1] = rp[i] + p[i];


	mcf<int> mc(2*n + 1);
	rep(i, n) {
		mc.add_edge(i, i + n, 1, 0);
		mc.add_edge(i, i + n, 2, p[i]);

		mc.add_edge(i + n, 2 * n, 2, rp[n] - rp[i + 1]);
	}
	rep(i, n)Rep(j, i+1, n) {
		int idl = i;
		int idr = j;
		int dx = abs(x[idl] - x[idr]);
		int dt = t[idr] - t[idl];
		if (v * dt >= dx) {
			mc.add_edge(idl + n, idr, 2, rp[idr] - rp[idl + 1]);
		}
	}

	int ans = 0;
	ans += mc.minimum_cost_flow(0, 2*n, 1);
	//cout << rp[n] - ans << "\n";
	ans += mc.minimum_cost_flow(1, 2 * n, 1);

	ans = 2 * rp[n] - ans;
	cout << ans << "\n";
}



signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(10);
	//init_f();
	//init();
	//int t; cin >> t; rep(i, t)
	//while (cin>>s,s!=".")
		solve();
	return 0;
}
accuracy: 1
time_ms: 780
memory_kb: 243348
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=998244353,MAX=6005,INF=1<<29;
typedef pair<int,int> P;

struct edge{int to,cap,cost,rev;};

int V;
vector<edge> G[MAX];
int h[MAX];
int dist[MAX];
int prevv[MAX],preve[MAX];
vector<int> id;

void add_edge(int from,int to,int cap,int cost){
    G[from].push_back((edge){to,cap,cost,int(G[to].size())});
    G[to].push_back((edge){from,0,-cost,int(G[from].size()-1)});
}

int min_cost_flow(int s,int t,int f){
    int res=0;
    fill(h,h+V,0);
    for(int v:id){
        for(auto e:G[v]){
            if(e.cap>0) chmin(h[e.to],h[v]+e.cost);
        }
    }
    
    while(f>0){
        priority_queue<P,vector<P>,greater<P>> que;
        fill(dist,dist+V,INF);
        dist[s]=0;
        que.push(P(0,s));
        while(!que.empty()){
            P p=que.top();que.pop();
            int v=p.second;
            if(dist[v]<p.first) continue;
            for(int i=0;i<G[v].size();i++){
                edge &e=G[v][i];
                if(e.cap>0&&dist[e.to]>dist[v]+e.cost+h[v]-h[e.to]){
                    dist[e.to]=dist[v]+e.cost+h[v]-h[e.to];
                    prevv[e.to]=v;
                    preve[e.to]=i;
                    que.push(P(dist[e.to],e.to));
                }
            }
        }
        
        if(dist[t]==INF){
            return -1;
        }
        for(int v=0;v<V;v++){
            h[v]+=dist[v];
        }
        
        int d=f;
        for(int v=t;v!=s;v=prevv[v]){
            d=min(d,G[prevv[v]][preve[v]].cap);
        }
        f-=d;
        res+=d*h[t];
        for(int v=t;v!=s;v=prevv[v]){
            edge &e=G[prevv[v]][preve[v]];
            e.cap-=d;
            G[v][e.rev].cap+=d;
        }
    }
    return res;
}//sからtへの流量fの最小費用流、流せない場合は-1

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    ll N,VV,xl,xr;cin>>N>>VV>>xl>>xr;
    vector<ll> X(N),T(N),P(N);
    for(int i=0;i<N;i++) cin>>X[i]>>T[i]>>P[i];
    V=2*N+4;
    int s=2*N,t=s+1,sl=s+2,sr=s+3;
    
    for(int i=0;i<N;i++){
        add_edge(i,N+i,1,-P[i]);
        add_edge(i,N+i,1,0);
        add_edge(N+i,t,2,0);
        
        if(abs(X[i]-xl)<=VV*T[i]) add_edge(sl,i,1,0);
        if(abs(X[i]-xr)<=VV*T[i]) add_edge(sr,i,1,0);
        
        for(int j=0;j<N;j++){
            if(T[i]>=T[j]) continue;
            if(abs(X[i]-X[j])<=VV*(T[j]-T[i])) add_edge(N+i,j,2,0);
        }
    }
    add_edge(s,sl,1,0);
    add_edge(s,sr,1,0);
    add_edge(s,t,2,0);
    
    vector<pair<ll,int>> S(N);
    for(int i=0;i<N;i++) S[i]=mp(T[i],i);
    sort(all(S));
    id.push_back(s);
    id.push_back(sl);
    id.push_back(sr);
    for(auto a:S){
        id.push_back(a.se);
        id.push_back(N+a.se);
    }
    id.push_back(t);
    
    cout<<-min_cost_flow(s,t,2)<<endl;
}
accuracy: 1
time_ms: 890
memory_kb: 244012
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=998244353,MAX=6005;
const ll INF=1LL<<57;

typedef pair<ll,int> P;

struct edge{int to,cap;ll cost;int rev;};

int V;
vector<edge> G[MAX];
ll h[MAX];
ll dist[MAX];
int prevv[MAX],preve[MAX];
vector<int> id;

void add_edge(int from,int to,int cap,ll cost){
    G[from].push_back((edge){to,cap,cost,int(G[to].size())});
    G[to].push_back((edge){from,0,-cost,int(G[from].size()-1)});
}

ll min_cost_flow(int s,int t,int f){
    ll res=0;
    fill(h,h+V,0);
    for(int v:id){
        for(auto e:G[v]){
            if(e.cap>0) chmin(h[e.to],h[v]+e.cost);
        }
    }
    
    while(f>0){
        priority_queue<P,vector<P>,greater<P>> que;
        fill(dist,dist+V,INF);
        dist[s]=0;
        que.push(P(0,s));
        while(!que.empty()){
            P p=que.top();que.pop();
            int v=p.second;
            if(dist[v]<p.first) continue;
            for(int i=0;i<G[v].size();i++){
                edge &e=G[v][i];
                if(e.cap>0&&dist[e.to]>dist[v]+e.cost+h[v]-h[e.to]){
                    dist[e.to]=dist[v]+e.cost+h[v]-h[e.to];
                    prevv[e.to]=v;
                    preve[e.to]=i;
                    que.push(P(dist[e.to],e.to));
                }
            }
        }
        
        if(dist[t]==INF){
            return -1;
        }
        for(int v=0;v<V;v++){
            h[v]+=dist[v];
        }
        
        int d=f;
        for(int v=t;v!=s;v=prevv[v]){
            d=min(d,G[prevv[v]][preve[v]].cap);
        }
        f-=d;
        res+=d*h[t];
        for(int v=t;v!=s;v=prevv[v]){
            edge &e=G[prevv[v]][preve[v]];
            e.cap-=d;
            G[v][e.rev].cap+=d;
        }
    }
    return res;
}//sからtへの流量fの最小費用流、流せない場合は-1

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    ll N,VV,xl,xr;cin>>N>>VV>>xl>>xr;
    vector<ll> X(N),T(N),P(N);
    for(int i=0;i<N;i++) cin>>X[i]>>T[i]>>P[i];
    V=2*N+2;
    int s=2*N,t=s+1;
    
    for(int i=0;i<N;i++){
        add_edge(i,N+i,1,-P[i]);
        add_edge(i,N+i,1,0);
        add_edge(N+i,t,2,0);
        
        if(abs(X[i]-xl)<=VV*T[i]) add_edge(s,i,1,0);
        if(abs(X[i]-xr)<=VV*T[i]) add_edge(s,i,1,0);
        
        for(int j=0;j<N;j++){
            if(T[i]>=T[j]) continue;
            if(abs(X[i]-X[j])<=VV*(T[j]-T[i])) add_edge(N+i,j,2,0);
        }
    }
    add_edge(s,t,2,0);
    
    vector<pair<ll,int>> S(N);
    for(int i=0;i<N;i++) S[i]=mp(T[i],i);
    sort(all(S));
    id.push_back(s);
    for(auto a:S){
        id.push_back(a.se);
        id.push_back(N+a.se);
    }
    id.push_back(t);
    
    cout<<-min_cost_flow(s,t,2)<<endl;
}
accuracy: 0.2653061224489796
time_ms: 150
memory_kb: 133056
final_rank: 20

code_snippet: #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2290"

#include<bits/stdc++.h>
using namespace std;

#define call_from_test
#ifndef call_from_test
#include<bits/stdc++.h>
using namespace std;
#endif
//BEGIN CUT HERE
// O(F E log V)
template<typename Flow, typename Cost>
struct PrimalDual{
  struct Edge{
    int dst;
    Flow cap;
    Cost cost;
    int rev;
    Edge(int dst,Flow cap,Cost cost,int rev):
      dst(dst),cap(cap),cost(cost),rev(rev){}
  };

  vector<vector<Edge>> G;
  vector<Cost> h,dist;
  vector<int> prevv,preve;

  PrimalDual(int n):G(n),h(n),dist(n),prevv(n),preve(n){}

  void add_edge(int u,int v,Flow cap,Cost cost){
    int e=G[u].size();
    int r=(u==v?e+1:G[v].size());
    G[u].emplace_back(v,cap,cost,r);
    G[v].emplace_back(u,0,-cost,e);
  }

  Cost residual_cost(int src,Edge &e){
    return e.cost+h[src]-h[e.dst];
  }

  void dijkstra(int s){
    struct P{
      Cost first;
      int second;
      P(Cost first,int second):first(first),second(second){}
      bool operator<(const P&a) const{return first>a.first;}
    };
    priority_queue<P> pq;

    dist[s]=0;
    pq.emplace(dist[s],s);
    while(!pq.empty()){
      P p=pq.top();pq.pop();
      int v=p.second;
      if(dist[v]<p.first) continue;
      for(int i=0;i<(int)G[v].size();i++){
        Edge &e=G[v][i];
        if(e.cap==0) continue;
        if(dist[v]+residual_cost(v,e)<dist[e.dst]){
          dist[e.dst]=dist[v]+e.cost+h[v]-h[e.dst];
          prevv[e.dst]=v;
          preve[e.dst]=i;
          pq.emplace(dist[e.dst],e.dst);
        }
      }
    }
  }

  Cost res;

  bool build(int s,int t,Flow f,
             function<void(decltype(h)&)> init=[](decltype(h) &p){
               fill(p.begin(),p.end(),0);
             }){
    res=0;
    init(h);
    const Cost INF = numeric_limits<Cost>::max();
    while(f>0){
      fill(dist.begin(),dist.end(),INF);
      dijkstra(s);
      if(dist[t]==INF) return false;

      for(int v=0;v<(int)h.size();v++)
        if(dist[v]<INF) h[v]=h[v]+dist[v];

      Flow d=f;
      for(int v=t;v!=s;v=prevv[v])
        d=min(d,G[prevv[v]][preve[v]].cap);

      f-=d;
      res=res+h[t]*d;
      for(int v=t;v!=s;v=prevv[v]){
        Edge &e=G[prevv[v]][preve[v]];
        e.cap-=d;
        G[v][e.rev].cap+=d;
      }
    }
    return true;
  }

  Cost get_cost(){return res;}
};
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed geocon2013_B(){
  cin.tie(0);
  ios::sync_with_stdio(0);

  using D = double;

  int n;
  cin>>n;
  vector<D> xs(n),ys(n);
  for(int i=0;i<n;i++) cin>>xs[i]>>ys[i];

  vector<int> pos,neg;
  for(int i=0;i<n;i++){
    if(xs[i]>0) pos.emplace_back(i);
    if(xs[i]<0) neg.emplace_back(i);
  }

  int f=max(pos.size(),neg.size());
  if(f==0){
    cout<<0<<endl;
    return 0;
  }

  PrimalDual<int, D> G(n+3);
  int S=n,T=n+1,U=n+2;
  for(int z:pos) G.add_edge(S,z,1,0);
  for(int z:neg) G.add_edge(z,T,1,0);

  int dif=pos.size()-neg.size();
  if(dif>0){
    G.add_edge(U,T,dif,0);
    for(int p:pos)
      G.add_edge(p,U,1,abs(xs[p]));
  }
  if(dif<0){
    G.add_edge(S,U,-dif,0);
    for(int q:neg)
      G.add_edge(U,q,1,abs(xs[q]));
  }

  for(int p:pos)
    for(int q:neg)
      G.add_edge(p,q,1,
                 min(hypot(xs[p]+xs[q],ys[p]-ys[q]),abs(xs[p])+abs(xs[q])));

  assert(G.build(S,T,f));
  cout<<fixed<<setprecision(12)<<G.get_cost()<<endl;
  return 0;
}
/*
  verified on 2020/09/25
  https://atcoder.jp/contests/geocon2013/tasks/geocon2013_b
*/

signed main(){
  geocon2013_B();
  return 0;
}
#endif


#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;
#endif
//BEGIN CUT HERE
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}
//END CUT HERE
#ifndef call_from_test
signed main(){
  return 0;
}
#endif


#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;
#endif

//BEGIN CUT HERE
vector<int> identity(int n){
  vector<int> ord(n);
  iota(ord.begin(),ord.end(),0);
  return ord;
}
//END CUT HERE
#ifndef call_from_test
signed main(){
  return 0;
}
#endif

#undef call_from_test

signed main(){
  cin.tie(0);
  ios::sync_with_stdio(0);

  int n,v,xleft,xright;
  cin>>n>>v>>xleft>>xright;

  int S=n+n,T=n+n+1,L=n+n+2,R=n+n+3;
  PrimalDual<int, int> G(n+n+4);

  G.add_edge(S,L,1,0);
  G.add_edge(L,T,1,0);

  G.add_edge(S,R,1,0);
  G.add_edge(R,T,1,0);

  vector<int> xs(n),ts(n),ps(n);
  for(int i=0;i<n;i++){
    cin>>xs[i]>>ts[i]>>ps[i];

    if(abs(xs[i]-xleft)<=ts[i]*v)
      G.add_edge(L,i,1,0);

    if(abs(xs[i]-xright)<=ts[i]*v)
      G.add_edge(R,i,1,0);
  }

  auto init=[&](auto &h)->void{
    fill(h.begin(),h.end(),0);

    auto ord=identity(n);
    sort(ord.begin(),ord.end(),
         [&](int i,int j){return ts[i]<ts[j];});

    auto add_edge=[&](int u,int v,int f,int c){
      G.add_edge(u,v,f,c);
      chmin(h[v],h[u]+c);
    };

    for(int i=0;i<n;i++){
      int x=ord[i];
      add_edge(x,n+x,1,-ps[x]);
      for(int j=i+1;j<n;j++){
        int y=ord[j];
        if(abs(xs[x]-xs[y])<=(ts[y]-ts[x])*v)
          add_edge(n+x,y,1,0);
      }
      add_edge(n+x,T,1,0);
    }
  };
  assert(G.build(S,T,2,init));
  cout<<-G.get_cost()<<endl;
  return 0;
}
accuracy: 1
time_ms: 770
memory_kb: 245160
final_rank: 7

code_snippet: #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2290"

#include<bits/stdc++.h>
using namespace std;

#define call_from_test
#ifndef call_from_test
#include<bits/stdc++.h>
using namespace std;
#endif
//BEGIN CUT HERE
// O(F E log V)
template<typename Flow, typename Cost>
struct PrimalDual{
  struct Edge{
    int dst;
    Flow cap;
    Cost cost;
    int rev;
    Edge(int dst,Flow cap,Cost cost,int rev):
      dst(dst),cap(cap),cost(cost),rev(rev){}
  };

  vector<vector<Edge>> G;
  vector<Cost> h,dist;
  vector<int> prevv,preve;

  PrimalDual(int n):G(n),h(n),dist(n),prevv(n),preve(n){}

  void add_edge(int u,int v,Flow cap,Cost cost){
    int e=G[u].size();
    int r=(u==v?e+1:G[v].size());
    G[u].emplace_back(v,cap,cost,r);
    G[v].emplace_back(u,0,-cost,e);
  }

  Cost residual_cost(int src,Edge &e){
    return e.cost+h[src]-h[e.dst];
  }

  void dijkstra(int s){
    struct P{
      Cost first;
      int second;
      P(Cost first,int second):first(first),second(second){}
      bool operator<(const P&a) const{return first>a.first;}
    };
    priority_queue<P> pq;

    dist[s]=0;
    pq.emplace(dist[s],s);
    while(!pq.empty()){
      P p=pq.top();pq.pop();
      int v=p.second;
      if(dist[v]<p.first) continue;
      for(int i=0;i<(int)G[v].size();i++){
        Edge &e=G[v][i];
        if(e.cap==0) continue;
        if(dist[v]+residual_cost(v,e)<dist[e.dst]){
          dist[e.dst]=dist[v]+e.cost+h[v]-h[e.dst];
          prevv[e.dst]=v;
          preve[e.dst]=i;
          pq.emplace(dist[e.dst],e.dst);
        }
      }
    }
  }

  Cost res;

  bool build(int s,int t,Flow f,
             function<void(decltype(h)&)> init=[](decltype(h) &p){
               fill(p.begin(),p.end(),0);
             }){
    res=0;
    init(h);
    const Cost INF = numeric_limits<Cost>::max();
    while(f>0){
      fill(dist.begin(),dist.end(),INF);
      dijkstra(s);
      if(dist[t]==INF) return false;

      for(int v=0;v<(int)h.size();v++)
        if(dist[v]<INF) h[v]=h[v]+dist[v];

      Flow d=f;
      for(int v=t;v!=s;v=prevv[v])
        d=min(d,G[prevv[v]][preve[v]].cap);

      f-=d;
      res=res+h[t]*d;
      for(int v=t;v!=s;v=prevv[v]){
        Edge &e=G[prevv[v]][preve[v]];
        e.cap-=d;
        G[v][e.rev].cap+=d;
      }
    }
    return true;
  }

  Cost get_cost(){return res;}
};
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed geocon2013_B(){
  cin.tie(0);
  ios::sync_with_stdio(0);

  using D = double;

  int n;
  cin>>n;
  vector<D> xs(n),ys(n);
  for(int i=0;i<n;i++) cin>>xs[i]>>ys[i];

  vector<int> pos,neg;
  for(int i=0;i<n;i++){
    if(xs[i]>0) pos.emplace_back(i);
    if(xs[i]<0) neg.emplace_back(i);
  }

  int f=max(pos.size(),neg.size());
  if(f==0){
    cout<<0<<endl;
    return 0;
  }

  PrimalDual<int, D> G(n+3);
  int S=n,T=n+1,U=n+2;
  for(int z:pos) G.add_edge(S,z,1,0);
  for(int z:neg) G.add_edge(z,T,1,0);

  int dif=pos.size()-neg.size();
  if(dif>0){
    G.add_edge(U,T,dif,0);
    for(int p:pos)
      G.add_edge(p,U,1,abs(xs[p]));
  }
  if(dif<0){
    G.add_edge(S,U,-dif,0);
    for(int q:neg)
      G.add_edge(U,q,1,abs(xs[q]));
  }

  for(int p:pos)
    for(int q:neg)
      G.add_edge(p,q,1,
                 min(hypot(xs[p]+xs[q],ys[p]-ys[q]),abs(xs[p])+abs(xs[q])));

  assert(G.build(S,T,f));
  cout<<fixed<<setprecision(12)<<G.get_cost()<<endl;
  return 0;
}
/*
  verified on 2020/09/25
  https://atcoder.jp/contests/geocon2013/tasks/geocon2013_b
*/

signed main(){
  geocon2013_B();
  return 0;
}
#endif


#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;
#endif
//BEGIN CUT HERE
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}
//END CUT HERE
#ifndef call_from_test
signed main(){
  return 0;
}
#endif


#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;
#endif

//BEGIN CUT HERE
vector<int> identity(int n){
  vector<int> ord(n);
  iota(ord.begin(),ord.end(),0);
  return ord;
}
//END CUT HERE
#ifndef call_from_test
signed main(){
  return 0;
}
#endif

#undef call_from_test

signed main(){
  cin.tie(0);
  ios::sync_with_stdio(0);

  int n,v,xleft,xright;
  cin>>n>>v>>xleft>>xright;

  int S=n+n,T=n+n+1,L=n+n+2,R=n+n+3;
  PrimalDual<int, int> G(n+n+4);

  G.add_edge(S,L,1,0);
  G.add_edge(L,T,1,0);

  G.add_edge(S,R,1,0);
  G.add_edge(R,T,1,0);

  vector<int> xs(n),ts(n),ps(n);
  for(int i=0;i<n;i++){
    cin>>xs[i]>>ts[i]>>ps[i];

    if(abs(xs[i]-xleft)<=ts[i]*v)
      G.add_edge(L,i,1,0);

    if(abs(xs[i]-xright)<=ts[i]*v)
      G.add_edge(R,i,1,0);

    G.add_edge(i,n+i,1,-ps[i]);
    G.add_edge(n+i,T,1,0);
  }

  for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
      if(ts[i]<ts[j] and abs(xs[i]-xs[j])<=(ts[j]-ts[i])*v)
        G.add_edge(n+i,j,1,0);

  auto init=[&](auto &h)->void{
    auto ord=identity(n);
    sort(ord.begin(),ord.end(),
         [&](int i,int j){return ts[i]<ts[j];});
    fill(h.begin(),h.end(),0);

    for(int i=0;i<n;i++){
      int x=ord[i];
      chmin(h[n+x],h[x]-ps[x]);
      for(int j=i+1;j<n;j++){
        int y=ord[j];
        if(abs(xs[x]-xs[y])<=(ts[y]-ts[x])*v)
          chmin(h[y],h[n+x]);
      }
      chmin(h[T],h[n+x]);
    }
  };
  assert(G.build(S,T,2,init));
  cout<<-G.get_cost()<<endl;
  return 0;
}
accuracy: 1
time_ms: 1050
memory_kb: 243112
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;

using Int = long long;
const char newl = '\n';

template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}
template<typename T> void drop(const T &x){cout<<x<<endl;exit(0);}
template<typename T=int>
vector<T> read(size_t n){
  vector<T> ts(n);
  for(size_t i=0;i<n;i++) cin>>ts[i];
  return ts;
}


// O(F E log V)
template<typename Flow, typename Cost>
struct PrimalDual{
  struct Edge{
    int to;
    Flow cap;
    Cost cost;
    int rev;
    Edge(int to,Flow cap,Cost cost,int rev):
      to(to),cap(cap),cost(cost),rev(rev){}
  };

  vector<vector<Edge>> G;
  vector<Cost> h,dist;
  vector<int> prevv,preve;

  PrimalDual(int n):G(n),h(n),dist(n),prevv(n),preve(n){}

  void add_edge(int u,int v,Flow cap,Cost cost){
    int e=G[u].size();
    int r=(u==v?e+1:G[v].size());
    G[u].emplace_back(v,cap,cost,r);
    G[v].emplace_back(u,0,-cost,e);
  }

  void dijkstra(int s){
    // cout<<"dijkstra"<<endl;
    struct P{
      Cost first;
      int second;
      P(Cost first,int second):first(first),second(second){}
      bool operator<(const P&a) const{return first>a.first;}
    };
    priority_queue<P> pq;

    dist[s]=0;
    pq.emplace(dist[s],s);
    while(!pq.empty()){
      P p=pq.top();pq.pop();
      int v=p.second;
      if(dist[v]<p.first) continue;
      for(int i=0;i<(int)G[v].size();i++){
        Edge &e=G[v][i];
        if(e.cap==0) continue;
        // if(e.cost+h[v]-h[e.to]<0) cout<<e.cost+h[v]-h[e.to]<<endl;
        assert(e.cost+h[v]-h[e.to]>=0);
        if(dist[v]+e.cost+h[v]-h[e.to]<dist[e.to]){
          dist[e.to]=dist[v]+e.cost+h[v]-h[e.to];
          prevv[e.to]=v;
          preve[e.to]=i;
          pq.emplace(dist[e.to],e.to);
        }
      }
    }
  }

  Cost res;

  bool build(int s,int t,Flow f,
             function<void(decltype(h)&)> init=[](decltype(h) &p){
               fill(p.begin(),p.end(),0);
             }){
    res=0;
    init(h);
    const Cost INF = numeric_limits<Cost>::max();
    while(f>0){
      fill(dist.begin(),dist.end(),INF);
      dijkstra(s);
      if(dist[t]==INF) return false;

      for(int v=0;v<(int)h.size();v++)
        if(dist[v]<INF) h[v]=h[v]+dist[v];

      Flow d=f;
      for(int v=t;v!=s;v=prevv[v])
        d=min(d,G[prevv[v]][preve[v]].cap);

      f-=d;
      res=res+h[t]*d;
      for(int v=t;v!=s;v=prevv[v]){
        Edge &e=G[prevv[v]][preve[v]];
        e.cap-=d;
        G[v][e.rev].cap+=d;
      }
    }
    return true;
  }

  Cost get_cost(){return res;}
};


vector<int> identity(int n){
  vector<int> ord(n);
  iota(ord.begin(),ord.end(),0);
  return ord;
}

//INSERT ABOVE HERE
signed main(){
  cin.tie(0);
  ios::sync_with_stdio(0);

  int n,v,xleft,xright;
  cin>>n>>v>>xleft>>xright;

  int S=n+n,T=n+n+1,L=n+n+2,R=n+n+3;
  PrimalDual<int, int> G(n+n+4);

  G.add_edge(S,L,1,0);
  G.add_edge(L,T,1,0);

  G.add_edge(S,R,1,0);
  G.add_edge(R,T,1,0);

  vector<int> xs(n),ts(n),ps(n);
  for(int i=0;i<n;i++){
    cin>>xs[i]>>ts[i]>>ps[i];

    if(abs(xs[i]-xleft)<=ts[i]*v)
      G.add_edge(L,i,1,0);

    if(abs(xs[i]-xright)<=ts[i]*v)
      G.add_edge(R,i,1,0);

    G.add_edge(i,n+i,1,-ps[i]);
    G.add_edge(n+i,T,1,0);
  }

  for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
      if(ts[i]<ts[j] and abs(xs[i]-xs[j])<=(ts[j]-ts[i])*v)
        G.add_edge(n+i,j,1,0);

  auto init=[&](auto &h)->void{
    auto ord=identity(n);
    sort(ord.begin(),ord.end(),
         [&](int i,int j){return ts[i]<ts[j];});
    fill(h.begin(),h.end(),0);

    for(int i=0;i<n;i++){
      int x=ord[i];
      chmin(h[n+x],h[x]-ps[x]);
      for(int j=i+1;j<n;j++){
        int y=ord[j];
        if(abs(xs[x]-xs[y])<=(ts[y]-ts[x])*v)
          chmin(h[y],h[n+x]);
      }
      chmin(h[T],h[n+x]);
    }
  };
  assert(G.build(S,T,2,init));
  cout<<-G.get_cost()<<endl;
  return 0;
}
accuracy: 1
time_ms: 1020
memory_kb: 243100
final_rank: 14

code_snippet: #include <bits/stdc++.h>

using namespace std;

using int64 = long long;
const int mod = 1e9 + 7;
// const int mod = 998244353;

const int64 infll = (1LL << 62) - 1;
const int inf = (1 << 30) - 1;

struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    cerr << fixed << setprecision(10);
  }
} iosetup;


template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 > &p) {
  os << p.first << " " << p.second;
  return os;
}

template< typename T1, typename T2 >
istream &operator>>(istream &is, pair< T1, T2 > &p) {
  is >> p.first >> p.second;
  return is;
}

template< typename T >
ostream &operator<<(ostream &os, const vector< T > &v) {
  for(int i = 0; i < (int) v.size(); i++) {
    os << v[i] << (i + 1 != v.size() ? " " : "");
  }
  return os;
}

template< typename T >
istream &operator>>(istream &is, vector< T > &v) {
  for(T &in : v) is >> in;
  return is;
}

template< typename T1, typename T2 >
inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }

template< typename T1, typename T2 >
inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }

template< typename T = int64 >
vector< T > make_v(size_t a) {
  return vector< T >(a);
}

template< typename T, typename... Ts >
auto make_v(size_t a, Ts... ts) {
  return vector< decltype(make_v< T >(ts...)) >(a, make_v< T >(ts...));
}

template< typename T, typename V >
typename enable_if< is_class< T >::value == 0 >::type fill_v(T &t, const V &v) {
  t = v;
}

template< typename T, typename V >
typename enable_if< is_class< T >::value != 0 >::type fill_v(T &t, const V &v) {
  for(auto &e : t) fill_v(e, v);
}

template< typename F >
struct FixPoint : F {
  FixPoint(F &&f) : F(forward< F >(f)) {}

  template< typename... Args >
  decltype(auto) operator()(Args &&... args) const {
    return F::operator()(*this, forward< Args >(args)...);
  }
};

template< typename F >
inline decltype(auto) MFP(F &&f) {
  return FixPoint< F >{forward< F >(f)};
}

template< typename CapType, typename CostType >
class MinCostFlowDAG {
public:
  using Cat = CapType;
  using Cot = CostType;
  using pti = pair< Cot, int >;
  struct edge {
    int to, rev;
    Cat cap;
    Cot cost;
  };
  const int V;
  const Cot inf;
  vector< vector< edge > > G;
  vector< Cot > h, dist;
  vector< int > deg, ord, prevv, preve;

  MinCostFlowDAG(const int node_size) : V(node_size), inf(numeric_limits< Cot >::max() / 4),
                                        G(V), h(V, inf), dist(V), deg(V, 0), prevv(V), preve(V) {}

  void add_edge(const int from, const int to, const Cat cap, const Cot cost) {
    G[from].push_back((edge) {to, (int) G[to].size(), cap, cost});
    G[to].push_back((edge) {from, (int) G[from].size() - 1, 0, -cost});
    ++deg[to];
  }

  bool tsort() {
    queue< int > que;
    for(int i = 0; i < V; ++i) {
      if(deg[i] == 0) que.push(i);
    }
    while(!que.empty()) {
      const int p = que.front();
      que.pop();
      ord.push_back(p);
      for(auto &e : G[p]) {
        if(e.cap > 0 && --deg[e.to] == 0) que.push(e.to);
      }
    }
    return (*max_element(deg.begin(), deg.end()) == 0);
  }

  void calc_potential(const int s) {
    h[s] = 0;
    for(const int v : ord) {
      if(h[v] == inf) continue;
      for(edge &e : G[v]) {
        if(e.cap > 0) h[e.to] = min(h[e.to], h[v] + e.cost);
      }
    }
  }

  void Dijkstra(const int s) {
    priority_queue< pti, vector< pti >, greater< pti > > que;
    fill(dist.begin(), dist.end(), inf);
    dist[s] = 0;
    que.push(pti(0, s));
    while(!que.empty()) {
      pti p = que.top();
      que.pop();
      const int v = p.second;
      if(dist[v] < p.first) continue;
      for(int i = 0; i < (int) G[v].size(); ++i) {
        edge &e = G[v][i];
        if(e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
          dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
          prevv[e.to] = v, preve[e.to] = i;
          que.push(pti(dist[e.to], e.to));
        }
      }
    }
  }

  void update(const int s, const int t, Cat &f, Cot &res) {
    for(int i = 0; i < V; i++) {
      h[i] += dist[i];
    }
    Cat d = f;
    for(int v = t; v != s; v = prevv[v]) {
      d = min(d, G[prevv[v]][preve[v]].cap);
    }
    f -= d;
    res += h[t] * d;
    for(int v = t; v != s; v = prevv[v]) {
      edge &e = G[prevv[v]][preve[v]];
      e.cap -= d;
      G[v][e.rev].cap += d;
    }
  }

  Cot solve(const int s, const int t, Cat f) {
    if(!tsort()) assert(false); // not DAG
    calc_potential(s);
    Cot res = 0;
    while(f > 0) {
      Dijkstra(s);
      if(dist[t] == inf) return -inf;
      update(s, t, f, res);
    }
    return res;
  }
};

int main() {
  int N, V, X[2];
  cin >> N >> V >> X[0] >> X[1];
  vector< int > P(N), T(N), S(N);
  for(int i = 0; i < N; i++) {
    cin >> P[i] >> T[i] >> S[i];
  }
  int src = 2 * N;
  int snk = src + 1;
  int latte = snk + 1;
  int malta = latte + 1;
  MinCostFlowDAG< int, int > flow(2 * N + 4);
  for(int i = 0; i < N; i++) {
    flow.add_edge(2 * i, 2 * i + 1, 1, -S[i]);
    flow.add_edge(2 * i + 1, snk, 1, 0);
    if(abs(X[0] - P[i]) <= 1LL * T[i] * V) flow.add_edge(latte, 2 * i, 1, 0);
    if(abs(X[1] - P[i]) <= 1LL * T[i] * V) flow.add_edge(malta, 2 * i, 1, 0);
    for(int j = 0; j < N; j++) {
      if(i == j) continue;
      if(abs(P[i] - P[j]) <= 1LL * V * (T[j] - T[i])) {
        flow.add_edge(2 * i + 1, 2 * j, 1, 0);
      }
    }
  }
  flow.add_edge(src, snk, 2, 0);
  flow.add_edge(src, latte, 1, 0);
  flow.add_edge(src, malta, 1, 0);
  cout << -flow.solve(src, snk, 2) << endl;
}
accuracy: 1
time_ms: 1200
memory_kb: 242392
final_rank: 18

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}


template<typename ...Ts>
decltype(auto) zip(vector<Ts>... args){
  vector<decltype(make_tuple(args[0]...))> res;
  int n=min({args.size()...});
  res.reserve(n);
  for(int i=0;i<n;i++) res.emplace_back(args[i]...);
  return res;
}

template<typename V>
V compress(V v){
  sort(v.begin(),v.end());
  v.erase(unique(v.begin(),v.end()),v.end());
  return v;
}
template<typename T>
map<T, int> dict(const vector<T> &v){
  map<T, int> res;
  for(int i=0;i<(int)v.size();i++)
    res[v[i]]=i;
  return res;
}
map<char, int> dict(const string &v){
  return dict(vector<char>(v.begin(),v.end()));
}


template<typename F>
struct FixPoint : F{
  FixPoint(F&& f):F(forward<F>(f)){}
  template<typename... Args>
  decltype(auto) operator()(Args&&... args) const{
    return F::operator()(*this,forward<Args>(args)...);
  }
};
template<typename F>
inline decltype(auto) MFP(F&& f){
  return FixPoint<F>{forward<F>(f)};
}

//INSERT ABOVE HERE
const int MAX = 3030;
int dp[MAX][MAX]={};
int rs[MAX][MAX]={};

const int INF = 1e9;
template<typename T>
struct BIT{
  int n;
  vector<T> bit;
  //1-indexed
  BIT(int n_):n(n_+2),bit(n,-INF){}

  T sum(int i){
    i++;

    T s(-INF);
    for(int x=i;x>0;x-=(x&-x))
      chmax(s,bit[x]);
    return s;
  }

  void add(int i,T a){
    i++;

    for(int x=i;x<n;x+=(x&-x))
      chmax(bit[x],a);
  }
};

signed main(){
  int n,v,xl,xr;
  cin>>n>>v>>xl>>xr;

  vector<int> xs(n),ts(n),ps(n);
  for(int i=0;i<n;i++) cin>>xs[i]>>ts[i]>>ps[i];
  xs.emplace_back(xl);
  ts.emplace_back(0);
  ps.emplace_back(0);
  xs.emplace_back(xr);
  ts.emplace_back(0);
  ps.emplace_back(0);

  xs.emplace_back(0);
  ts.emplace_back(INF);
  ps.emplace_back(0);

  n=xs.size();
  auto zs=zip(ts,xs,ps);
  sort(zs.begin(),zs.end());
  for(int i=0;i<n;i++)
    tie(ts[i],xs[i],ps[i])=zs[i];

  using ll = long long;
  for(int i=0;i<n;i++)
    for(int j=i+1;j<n;j++)
      rs[i][j]=abs(xs[j]-xs[i])<=(ll)v*(ts[j]-ts[i]);

  for(int i=0;i<MAX;i++)
    for(int j=0;j<MAX;j++)
      dp[i][j]=-INF;
  dp[0][1]=0;

  vector<ll> as(n),bs(n);
  for(int i=0;i<n;i++){
    as[i]=-xs[i]+(ll)v*ts[i];
    bs[i]=+xs[i]+(ll)v*ts[i];
  }

  auto da=dict(compress(as));
  auto db=dict(compress(bs));
  vector<int> va(n),vb(n);
  for(int i=0;i<n;i++){
    va[i]=da[as[i]];
    vb[i]=db[bs[i]];
  }

  using P = pair<ll, ll>;
  vector<P> vp,vq;
  for(int l=0;l<n;l++){
    vp.emplace_back(+xs[l],l);
    vq.emplace_back(-xs[l],l);
  }
  sort(vp.begin(),vp.end());
  sort(vq.begin(),vq.end());

  for(int c=1;c<n;c++){
    {
      MFP([&](auto dfs,int l,int r)->void{
            if(l+1==r) return;
            int m=(l+r)>>1;

            dfs(l,m);

            if(r-l<=100){
              for(int a=l;a<m;a++)
                for(int b=m;b<r;b++)
                  if(rs[a][b])
                    chmax(dp[b][c],dp[a][c]+ps[b]);

            }else{
              for(int k=0;k<2;k++){
                vector<P> vp;
                for(int a=l;a<m;a++)
                  vp.emplace_back(k?+xs[a]:-xs[a],a+0);
                for(int b=m;b<r;b++)
                  vp.emplace_back(k?+xs[b]:-xs[b],b+n);
                sort(vp.begin(),vp.end());

                vector<ll> vs;
                for(int i=l;i<r;i++)
                  vs.emplace_back(k?as[i]:bs[i]);
                auto cs=compress(vs);
                vector<ll> ws(r-l);
                for(int i=0;i<r-l;i++)
                  ws[i]=lower_bound(cs.begin(),cs.end(),vs[i])-cs.begin();

                BIT<int> bit(cs.size());
                for(auto p:vp){
                  if(p.second<n){
                    int a=p.second;
                    bit.add(ws[a-l],dp[a][c]);
                  }else{
                    int b=p.second-n;
                    chmax(dp[b][c],bit.sum(ws[b-l])+ps[b]);
                  }
                }
              }
            }

            dfs(m,r);
          })(0,c);
    }


    for(int k=0;k<2;k++){
      auto &vv=k?vp:vq;
      auto &vw=k?va:vb;
      BIT<int> bit(n+10);
      for(auto p:vv){
        if(p.second<c){
          int l=p.second;
          bit.add(vw[l],dp[l][c]);
        }
        if(p.second>c){
          int r=p.second;
          chmax(dp[c][r],bit.sum(vw[r])+ps[r]);
        }
      }
    }
  }

  int ans=0;
  for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
      chmax(ans,dp[i][j]);

  cout<<ans<<endl;
  return 0;
}
accuracy: 1
time_ms: 5920
memory_kb: 67332
final_rank: 4

code_snippet: //#define NDEBUG
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <utility>
#include <vector>

namespace n91 {

using i8 = std::int_fast8_t;
using i32 = std::int_fast32_t;
using i64 = std::int_fast64_t;
using u8 = std::uint_fast8_t;
using u32 = std::uint_fast32_t;
using u64 = std::uint_fast64_t;
using isize = std::ptrdiff_t;
using usize = std::size_t;

struct rep {
  struct itr {
    usize i;
    constexpr itr(const usize i) noexcept : i(i) {}
    void operator++() noexcept { ++i; }
    constexpr usize operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr x) const noexcept { return i != x.i; }
  };
  const itr f, l;
  constexpr rep(const usize f, const usize l) noexcept
      : f(std::min(f, l)), l(l) {}
  constexpr auto begin() const noexcept { return f; }
  constexpr auto end() const noexcept { return l; }
};
struct revrep {
  struct itr {
    usize i;
    constexpr itr(const usize i) noexcept : i(i) {}
    void operator++() noexcept { --i; }
    constexpr usize operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr x) const noexcept { return i != x.i; }
  };
  const itr f, l;
  constexpr revrep(const usize f, const usize l) noexcept
      : f(l - 1), l(std::min(f, l) - 1) {}
  constexpr auto begin() const noexcept { return f; }
  constexpr auto end() const noexcept { return l; }
};
template <class T> auto md_vec(const usize n, const T &value) {
  return std::vector<T>(n, value);
}
template <class... Args> auto md_vec(const usize n, Args... args) {
  return std::vector<decltype(md_vec(args...))>(n, md_vec(args...));
}
template <class T> constexpr T difference(const T &a, const T &b) noexcept {
  if (a < b) {
    return b - a;
  } else {
    return a - b;
  }
}
template <class T> void chmin(T &a, const T &b) noexcept {
  if (b < a) {
    a = b;
  }
}
template <class T> void chmax(T &a, const T &b) noexcept {
  if (a < b) {
    a = b;
  }
}
template <class F> class fix_point : private F {
public:
  explicit constexpr fix_point(F &&f) : F(std::forward<F>(f)) {}

  template <class... Args>
  constexpr decltype(auto) operator()(Args &&... args) const {
    return F::operator()(*this, std::forward<Args>(args)...);
  }
};
template <class F> constexpr decltype(auto) make_fix(F &&f) {
  return fix_point<F>(std::forward<F>(f));
}
template <class T> T scan() {
  T ret;
  std::cin >> ret;
  return ret;
}

} // namespace n91
#include <cassert>
#include <cstddef>
#include <vector>

template <class Monoid> class segment_tree {
public:
  using T = typename Monoid::value_type;
  using size_t = std::size_t;

private:
  std::vector<T> tree;

  template <class F>
  size_t search_subtree(size_t index, const F f, T fold_l) const {
    while (index < size()) {
      const T temp = Monoid::operation(fold_l, tree[index * 2]);
      if (!f(temp)) {
        index = index * 2;
      } else {
        fold_l = temp;
        index = index * 2 + 1;
      }
    }
    return index - size();
  }

public:
  segment_tree() = default;
  explicit segment_tree(const size_t n) : tree(n * 2, Monoid::identity) {}

  size_t size() const noexcept { return tree.size() / 2; }

  T fold(size_t first, size_t last) const {
    assert(first <= last);
    assert(last <= size());
    first += size();
    last += size();
    T fold_l = Monoid::identity;
    T fold_r = Monoid::identity;
    while (first != last) {
      if (first % 2 != 0) {
        fold_l = Monoid::operation(fold_l, tree[first]);
        first += 1;
      }
      first /= 2;
      if (last % 2 != 0) {
        last -= 1;
        fold_r = Monoid::operation(tree[last], fold_r);
      }
      last /= 2;
    }
    return Monoid::operation(fold_l, fold_r);
  }
  template <class F> size_t search(size_t first, size_t last, const F f) const {
    assert(first <= last);
    assert(last <= size());
    first += size();
    last += size();
    const size_t last_cp = last;
    size_t shift = 0;
    T fold_l = Monoid::identity;
    while (first != last) {
      if (first % 2 != 0) {
        const T temp = Monoid::operation(fold_l, tree[first]);
        if (!f(temp))
          return search_subtree(first, f, fold_l);
        fold_l = temp;
        first += 1;
      }
      first /= 2;
      last /= 2;
      shift += 1;
    }
    while (shift != 0) {
      shift -= 1;
      last = last_cp >> shift;
      if (last % 2 != 0) {
        last -= 1;
        const T temp = Monoid::operation(fold_l, tree[last]);
        if (!f(temp))
          return search_subtree(last, f, fold_l);
        fold_l = temp;
      }
    }
    return last_cp - size();
  }

  void update(size_t index, const T x) {
    assert(index < size());
    index += size();
    tree[index] = x;
    while (index != 1) {
      index /= 2;
      tree[index] = Monoid::operation(tree[index * 2], tree[index * 2 + 1]);
    }
  }
};
#include <algorithm>
#include <limits>

template <class T> class max_monoid {
public:
  using value_type = T;
  static constexpr T operation(const T &x, const T &y) noexcept {
    return std::max(x, y);
  }
  static constexpr T identity = std::numeric_limits<T>::lowest();
};
template <class T> constexpr T max_monoid<T>::identity;
#include <algorithm>
#include <iostream>
#include <map>
#include <tuple>
#include <utility>
#include <vector>

namespace n91 {

void main_() {
  /*
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  //*/
  const usize n = scan<usize>();
  const i32 v = scan<i32>();
  const i32 xl = scan<i32>();
  const i32 xr = scan<i32>();
  struct mogu_t {
    i32 x;
    i32 y;
    u32 p;
    bool f;
  };
  std::vector<mogu_t> ms(n);
  std::map<i32, usize> mp;
  for (auto &e : ms) {
    e.f = false;
    const i32 x = scan<i32>();
    const i32 t = scan<i32>();
    const u32 p = scan<u32>();
    e.x = -t * v + x;
    e.y = -t * v - x;
    e.p = p;
    mp[e.y];
  }
  ms.push_back({xl, -xl, 0, true});
  ms.push_back({xr, -xr, 0, true});
  mp[-xl];
  mp[-xr];
  {
    usize c = 0;
    for (auto &e : mp)
      e.second = c++;
  }
  std::sort(ms.begin(), ms.end(), [](auto l, auto r) {
    return std::tie(l.x, l.y) < std::tie(r.x, r.y);
  });
  using seg_t = segment_tree<max_monoid<u32>>;
  const usize m = mp.size();
  std::vector<seg_t> dp(m, seg_t(m));
  usize ph = 0;
  for (const auto &e : ms) {
    if (e.f) {
      ph += 1;
      continue;
    }
    const usize k = mp[e.y];
    if (ph <= 1)
      dp[k].update(k, dp[k].fold(0, k + 1) + e.p);
    for (const usize i : rep(0, m)) {
      if (i == k)
        continue;
      const u32 v = dp[i].fold(0, k + 1) + e.p;
      if (ph <= 1)
        dp[i].update(k, v);
      if (ph <= 0)
        dp[k].update(i, v);
    }
    /*
    std::cout << "\n";
    for (const auto i : rep(0, m)) {
      for (const auto j : rep(0, m)) {
        std::cout << dp[i].fold(j, j + 1) << " ";
      }
      std::cout << "\n";
    }
    */
  }
  u32 ans = 0;
  for (const auto i : rep(0, mp[-xl] + 1)) {
    chmax(ans, dp[i].fold(0, mp[-xr] + 1));
  }
  std::cout << ans << std::endl;
}

} // namespace n91

int main() {
  n91::main_();
  return 0;
}
accuracy: 1
time_ms: 1580
memory_kb: 144140
final_rank: 2

code_snippet: #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;
}
accuracy: 1
time_ms: 1150
memory_kb: 240728
final_rank: 17

code_snippet: // https://onlinejudge.u-aizu.ac.jp/challenges/search/categories/2290
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <limits>
template <typename T>
constexpr T INF() { return std::numeric_limits<T>::max() / 16; }
#include <vector>
template <typename Cap, typename Cost, typename Ind = std::size_t>
struct CostFlow
{
    CostFlow(const Ind v) : V(v), edge(v) { edge.shrink_to_fit(); }
    void addEdge(const Ind from, const Ind to, const Cap cap, const Cost cost) { edge[from].push_back(Edge{to, (Ind)edge[to].size(), cap, cost, false}), edge[to].push_back(Edge{from, (Ind)(edge[from].size() - 1), 0, -cost, true}); }
    struct Edge
    {
        Ind to, rev;
        Cap cap;
        Cost cost;
        const bool isrev;
    };
    const Ind V;
    std::vector<std::vector<Edge>> edge;
};
template <typename T, template <typename, typename, typename, typename> class PotFunc, typename Cap, typename Cost, typename Ind>
std::pair<bool, T> PrimalDual(CostFlow<Cap, Cost, Ind>& cflow, const Ind s, const Ind t, Cap f)
{
    const Ind V = cflow.V;
    T ans = 0;
    std::vector<T> potential = PotFunc<T, Cap, Cost, Ind>()(cflow, s);
    std::vector<T> dist(V, INF<T>());
    using P = std::pair<T, Ind>;
    std::priority_queue<P, std::vector<P>, std::greater<P>> Q;
    std::vector<Ind> prev_v(V), prev_e(V);
    dist.shrink_to_fit(), prev_v.shrink_to_fit(), prev_e.shrink_to_fit();
    while (f > 0) {
        std::fill(dist.begin(), dist.end(), INF<T>());
        dist[s] = 0, Q.push({0, s});
        while (not Q.empty()) {
            const T cost = Q.top().first;
            const Ind v = Q.top().second;
            Q.pop();
            if (dist[v] < cost) { continue; }
            for (Ind i = 0; i < (Ind)cflow.edge[v].size(); i++) {
                const auto& e = cflow.edge[v][i];
                const T pd = potential[v] - potential[e.to];
                if (e.cap == 0 or dist[e.to] <= dist[v] + (T)e.cost + pd) { continue; }
                dist[e.to] = dist[v] + (T)e.cost + pd, prev_v[e.to] = v, prev_e[e.to] = i;
                Q.push({dist[e.to], e.to});
            }
        }
        if (dist[t] == INF<T>()) { return {false, ans}; }
        for (Ind v = 0; v < V; v++) { potential[v] += dist[v]; }
        Cap d = f;
        for (Ind v = t; v != s; v = prev_v[v]) {
            const auto& e = cflow.edge[prev_v[v]][prev_e[v]];
            d = std::min(d, e.cap);
        }
        f = (Cap)(f - d), ans += (T)d * potential[t];
        for (Ind v = t; v != s; v = prev_v[v]) {
            auto& e = cflow.edge[prev_v[v]][prev_e[v]];
            e.cap = (Cap)(e.cap - d), cflow.edge[v][e.rev].cap = (Cap)(cflow.edge[v][e.rev].cap + d);
        }
    }
    return {true, ans};
}
#include <algorithm>
#include <algorithm>
#include <vector>
struct Graph
{
    Graph(const std::size_t v) : V{v}, edge(v), rev_edge(v) {}
    void addEdge(const std::size_t from, const std::size_t to) { edge[from].push_back(to), rev_edge[to].push_back(from); }
    const std::size_t V;
    std::vector<std::vector<std::size_t>> edge, rev_edge;
};
std::pair<bool, std::vector<std::size_t>> TopSort(const Graph& g)
{
    std::vector<std::size_t> srt, used(g.V, 0);
    auto dfs = [&](auto&& self, const std::size_t s) -> bool {
        if (used[s] == 1) {
            return false;
        } else if (used[s] == 0) {
            used[s] = 1;
            for (const std::size_t to : g.edge[s]) {
                if (not self(self, to)) { return false; }
            }
            used[s] = 2, srt.push_back(s);
        }
        return true;
    };
    for (std::size_t i = 0; i < g.V; i++) {
        if (not dfs(dfs, i)) { return {false, srt}; }
    }
    std::reverse(srt.begin(), srt.end());
    return {true, srt};
}
template <typename T, typename Cap, typename Cost, typename Ind>
struct PotDAG
{
    std::vector<T> operator()(const CostFlow<Cap, Cost, Ind>& cflow, const Ind s) const
    {
        const Ind V = cflow.V;
        std::vector<Ind> ord;
        std::vector<bool> used(V, 0);
        auto dfs = [&](auto&& self, const Ind s) -> void {
            if (not used[s]) {
                used[s] = true;
                for (const auto& e : cflow.edge[s]) {
                    if (e.cap == 0) { continue; }
                    self(self, e.to);
                }
                ord.push_back(s);
            }
        };
        for (Ind i = 0; i < V; i++) { dfs(dfs, i); }
        std::reverse(ord.begin(), ord.end());
        std::vector<T> ans(V, INF<T>());
        ans.shrink_to_fit();
        for (Ind i = 0; i < V; i++) {
            if (ord[i] == s) { ans[s] = (T)0; }
            for (const auto& e : cflow.edge[ord[i]]) {
                if (e.cap == 0) { continue; }
                ans[e.to] = std::min(ans[e.to], ans[ord[i]] + (T)e.cost);
            }
        }
        return ans;
    }
};
struct Point
{
    int X, T, P;
    bool operator<(const Point& p) const
    {
        return T < p.T;
    }
};

int main()
{
    short N;
    std::cin >> N;
    std::size_t V, L, R;
    std::cin >> V >> L >> R;
    std::vector<Point> point(N);
    point.shrink_to_fit();
    for (short i = 0; i < N; i++) { std::cin >> point[i].X >> point[i].T >> point[i].P; }
    std::sort(point.begin(), point.end());
    CostFlow<char, int, short> cflow((short)(2 * N + 4));
    const short s = 0, t = (short)(2 * N + 3), l = 1, r = 2;
    cflow.addEdge(s, l, 1, 0), cflow.addEdge(s, r, 1, 0);
    for (short i = 0; i < N; i++) {
        cflow.addEdge((short)(2 * i + 3), (short)(2 * i + 4), 1, 0), cflow.addEdge((short)(2 * i + 4), t, 1, -point[i].P);
        if (std::abs(point[i].X - (int)L) <= V * point[i].T) { cflow.addEdge(l, (short)(2 * i + 3), 1, 0); }
        if (std::abs(point[i].X - (int)R) <= V * point[i].T) { cflow.addEdge(r, (short)(2 * i + 3), 1, 0); }
    }
    for (short i = 0; i < N; i++) {
        for (short j = (short)(i + 1); j < N; j++) {
            if (std::abs(point[i].X - point[j].X) <= V * (point[j].T - point[i].T)) { cflow.addEdge((short)(2 * i + 4), (short)(2 * j + 3), 1, -point[i].P); }
        }
    }
    point.clear(), point.shrink_to_fit();
    std::cout << -PrimalDual<int, PotDAG>(cflow, s, t, (char)2).second << std::endl;

    return 0;
}
accuracy: 1
time_ms: 1010
memory_kb: 241836
final_rank: 11

code_snippet: // https://onlinejudge.u-aizu.ac.jp/challenges/search/categories/2290
// MLEです (頂点型をshortにして、容量型をcharにすると多分通ります)
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <limits>
template <typename T>
constexpr T INF() { return std::numeric_limits<T>::max() / 16; }
#include <vector>
template <typename Cap, typename Cost, typename Ind = std::size_t>
struct CostFlow
{
    CostFlow(const Ind v) : V(v), edge(v) { edge.shrink_to_fit(); }
    void addEdge(const Ind from, const Ind to, const Cap cap, const Cost cost) { edge[from].push_back(Edge{to, (Ind)edge[to].size(), cap, cost, false}), edge[to].push_back(Edge{from, (Ind)(edge[from].size() - 1), 0, -cost, true}); }
    struct Edge
    {
        Ind to, rev;
        Cap cap;
        Cost cost;
        const bool isrev;
    };
    const Ind V;
    std::vector<std::vector<Edge>> edge;
};
template <typename T, template <typename, typename, typename, typename> class PotFunc, typename Cap, typename Cost, typename Ind>
std::pair<bool, T> PrimalDual(CostFlow<Cap, Cost, Ind>& cflow, const Ind s, const Ind t, Cap f)
{
    const Ind V = cflow.V;
    T ans = 0;
    std::vector<T> potential = PotFunc<T, Cap, Cost, Ind>()(cflow, s);
    std::vector<T> dist(V, INF<T>());
    using P = std::pair<T, Ind>;
    std::priority_queue<P, std::vector<P>, std::greater<P>> Q;
    std::vector<Ind> prev_v(V), prev_e(V);
    dist.shrink_to_fit(), prev_v.shrink_to_fit(), prev_e.shrink_to_fit();
    while (f > 0) {
        std::fill(dist.begin(), dist.end(), INF<T>());
        dist[s] = 0, Q.push({0, s});
        while (not Q.empty()) {
            const T cost = Q.top().first;
            const Ind v = Q.top().second;
            Q.pop();
            if (dist[v] < cost) { continue; }
            for (Ind i = 0; i < cflow.edge[v].size(); i++) {
                const auto& e = cflow.edge[v][i];
                const T pd = potential[v] - potential[e.to];
                if (e.cap == 0 or dist[e.to] <= dist[v] + e.cost + pd) { continue; }
                dist[e.to] = dist[v] + e.cost + pd, prev_v[e.to] = v, prev_e[e.to] = i;
                Q.push({dist[e.to], e.to});
            }
        }
        if (dist[t] == INF<T>()) { return {false, ans}; }
        for (Ind v = 0; v < V; v++) { potential[v] += dist[v]; }
        Cap d = f;
        for (Ind v = t; v != s; v = prev_v[v]) {
            const auto& e = cflow.edge[prev_v[v]][prev_e[v]];
            d = std::min(d, e.cap);
        }
        f -= d, ans += (T)d * potential[t];
        for (Ind v = t; v != s; v = prev_v[v]) {
            auto& e = cflow.edge[prev_v[v]][prev_e[v]];
            e.cap -= d, cflow.edge[v][e.rev].cap += d;
        }
    }
    return {true, ans};
}
#include <algorithm>
#include <algorithm>
#include <vector>
struct Graph
{
    Graph(const std::size_t v) : V{v}, edge(v), rev_edge(v) {}
    void addEdge(const std::size_t from, const std::size_t to) { edge[from].push_back(to), rev_edge[to].push_back(from); }
    const std::size_t V;
    std::vector<std::vector<std::size_t>> edge, rev_edge;
};
std::pair<bool, std::vector<std::size_t>> TopSort(const Graph& g)
{
    std::vector<std::size_t> srt, used(g.V, 0);
    auto dfs = [&](auto&& self, const std::size_t s) -> bool {
        if (used[s] == 1) {
            return false;
        } else if (used[s] == 0) {
            used[s] = 1;
            for (const std::size_t to : g.edge[s]) {
                if (not self(self, to)) { return false; }
            }
            used[s] = 2, srt.push_back(s);
        }
        return true;
    };
    for (std::size_t i = 0; i < g.V; i++) {
        if (not dfs(dfs, i)) { return {false, srt}; }
    }
    std::reverse(srt.begin(), srt.end());
    return {true, srt};
}
template <typename T, typename Cap, typename Cost, typename Ind>
struct PotDAG
{
    std::vector<T> operator()(const CostFlow<Cap, Cost, Ind>& cflow, const Ind s) const
    {
        const Ind V = cflow.V;
        std::vector<Ind> ord;
        std::vector<bool> used(V, 0);
        auto dfs = [&](auto&& self, const Ind s) -> void {
            if (not used[s]) {
                used[s] = true;
                for (const auto& e : cflow.edge[s]) {
                    if (e.cap == 0) { continue; }
                    self(self, e.to);
                }
                ord.push_back(s);
            }
        };
        for (Ind i = 0; i < V; i++) { dfs(dfs, i); }
        std::reverse(ord.begin(), ord.end());
        std::vector<T> ans(V, INF<T>());
        ans.shrink_to_fit();
        for (Ind i = 0; i < V; i++) {
            if (ord[i] == s) { ans[s] = 0; }
            for (const auto& e : cflow.edge[ord[i]]) {
                if (e.cap == 0) { continue; }
                ans[e.to] = std::min(ans[e.to], ans[ord[i]] + e.cost);
            }
        }
        return ans;
    }
};
struct Point
{
    int X, T, P;
    bool operator<(const Point& p) const
    {
        return T < p.T;
    }
};

int main()
{
    short N;
    std::cin >> N;
    std::size_t V, L, R;
    std::cin >> V >> L >> R;
    std::vector<Point> point(N);
    point.shrink_to_fit();
    for (short i = 0; i < N; i++) { std::cin >> point[i].X >> point[i].T >> point[i].P; }
    std::sort(point.begin(), point.end());
    CostFlow<char, int, short> cflow(2 * N + 4);
    const short s = 0, t = 2 * N + 3, l = 1, r = 2;
    cflow.addEdge(s, l, 1, 0), cflow.addEdge(s, r, 1, 0);
    for (short i = 0; i < N; i++) {
        cflow.addEdge(2 * i + 3, 2 * i + 4, 1, 0), cflow.addEdge(2 * i + 4, t, 1, -point[i].P);
        if (std::abs(point[i].X - (int)L) <= V * point[i].T) { cflow.addEdge(l, 2 * i + 3, 1, 0); }
        if (std::abs(point[i].X - (int)R) <= V * point[i].T) { cflow.addEdge(r, 2 * i + 3, 1, 0); }
    }
    for (short i = 0; i < N; i++) {
        for (short j = i + 1; j < N; j++) {
            if (std::abs(point[i].X - point[j].X) <= V * (point[j].T - point[i].T)) { cflow.addEdge(2 * i + 4, 2 * j + 3, 1, -point[i].P); }
        }
    }
    point.clear(), point.shrink_to_fit();
    std::cout << -PrimalDual<int, PotDAG>(cflow, s, t, (char)2).second << std::endl;

    return 0;
}
accuracy: 1
time_ms: 1010
memory_kb: 241908
final_rank: 12

code_snippet: // https://onlinejudge.u-aizu.ac.jp/challenges/search/categories/2290
// MLEです (頂点型をshortにして、容量型をcharにすると多分通ります)
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <limits>
template <typename T>
constexpr T INF() { return std::numeric_limits<T>::max() / 16; }
#include <vector>
template <typename Cap, typename Cost, typename Ind = std::size_t>
struct CostFlow
{
    CostFlow(const Ind v) : V(v), edge(v) { edge.shrink_to_fit(); }
    void addEdge(const Ind from, const Ind to, const Cap cap, const Cost cost) { edge[from].push_back(Edge{to, (Ind)edge[to].size(), cap, cost, false}), edge[to].push_back(Edge{from, (Ind)(edge[from].size() - 1), 0, -cost, true}); }
    struct Edge
    {
        Ind to, rev;
        Cap cap;
        Cost cost;
        const bool isrev;
    };
    const Ind V;
    std::vector<std::vector<Edge>> edge;
};
template <typename T, template <typename, typename, typename, typename> class PotFunc, typename Cap, typename Cost, typename Ind>
std::pair<bool, T> PrimalDual(CostFlow<Cap, Cost, Ind>& cflow, const Ind s, const Ind t, Cap f)
{
    const Ind V = cflow.V;
    T ans = 0;
    std::vector<T> potential = PotFunc<T, Cap, Cost, Ind>()(cflow, s);
    std::vector<T> dist(V, INF<T>());
    using P = std::pair<T, Ind>;
    std::priority_queue<P, std::vector<P>, std::greater<P>> Q;
    std::vector<Ind> prev_v(V), prev_e(V);
    dist.shrink_to_fit(), prev_v.shrink_to_fit(), prev_e.shrink_to_fit();
    while (f > 0) {
        std::fill(dist.begin(), dist.end(), INF<T>());
        dist[s] = 0, Q.push({0, s});
        while (not Q.empty()) {
            const T cost = Q.top().first;
            const Ind v = Q.top().second;
            Q.pop();
            if (dist[v] < cost) { continue; }
            for (Ind i = 0; i < cflow.edge[v].size(); i++) {
                const auto& e = cflow.edge[v][i];
                const T pd = potential[v] - potential[e.to];
                if (e.cap == 0 or dist[e.to] <= dist[v] + e.cost + pd) { continue; }
                dist[e.to] = dist[v] + e.cost + pd, prev_v[e.to] = v, prev_e[e.to] = i;
                Q.push({dist[e.to], e.to});
            }
        }
        if (dist[t] == INF<T>()) { return {false, ans}; }
        for (Ind v = 0; v < V; v++) { potential[v] += dist[v]; }
        Cap d = f;
        for (Ind v = t; v != s; v = prev_v[v]) {
            const auto& e = cflow.edge[prev_v[v]][prev_e[v]];
            d = std::min(d, e.cap);
        }
        f -= d, ans += (T)d * potential[t];
        for (Ind v = t; v != s; v = prev_v[v]) {
            auto& e = cflow.edge[prev_v[v]][prev_e[v]];
            e.cap -= d, cflow.edge[v][e.rev].cap += d;
        }
    }
    return {true, ans};
}
#include <algorithm>
#include <vector>
struct Graph
{
    Graph(const std::size_t v) : V{v}, edge(v), rev_edge(v) {}
    void addEdge(const std::size_t from, const std::size_t to) { edge[from].push_back(to), rev_edge[to].push_back(from); }
    const std::size_t V;
    std::vector<std::vector<std::size_t>> edge, rev_edge;
};
std::pair<bool, std::vector<std::size_t>> TopSort(const Graph& g)
{
    std::vector<std::size_t> srt, used(g.V, 0);
    auto dfs = [&](auto&& self, const std::size_t s) -> bool {
        if (used[s] == 1) {
            return false;
        } else if (used[s] == 0) {
            used[s] = 1;
            for (const std::size_t to : g.edge[s]) {
                if (not self(self, to)) { return false; }
            }
            used[s] = 2, srt.push_back(s);
        }
        return true;
    };
    for (std::size_t i = 0; i < g.V; i++) {
        if (not dfs(dfs, i)) { return {false, srt}; }
    }
    std::reverse(srt.begin(), srt.end());
    return {true, srt};
}
template <typename T, typename Cap, typename Cost, typename Ind>
struct PotDAG
{
    std::vector<T> operator()(const CostFlow<Cap, Cost, Ind>& cflow, const Ind s) const
    {
        const Ind V = cflow.V;
        std::vector<Ind> ord(V);
        for (Ind i = 0; i < V; i++) { ord[i] = i; }
        std::vector<T> ans(V, INF<T>());
        ans.shrink_to_fit();
        for (Ind i = 0; i < V; i++) {
            if (ord[i] == s) { ans[s] = 0; }
            for (const auto& e : cflow.edge[ord[i]]) {
                if (e.cap == 0) { continue; }
                ans[e.to] = std::min(ans[e.to], ans[ord[i]] + e.cost);
            }
        }
        return ans;
    }
};
struct Point
{
    int X, T, P;
    bool operator<(const Point& p) const
    {
        return T < p.T;
    }
};

int main()
{
    short N;
    std::cin >> N;
    std::size_t V, L, R;
    std::cin >> V >> L >> R;
    std::vector<Point> point(N);
    point.shrink_to_fit();
    for (short i = 0; i < N; i++) { std::cin >> point[i].X >> point[i].T >> point[i].P; }
    std::sort(point.begin(), point.end());
    CostFlow<char, int, short> cflow(2 * N + 4);
    const short s = 0, t = 2 * N + 3, l = 1, r = 2;
    cflow.addEdge(s, l, 1, 0), cflow.addEdge(s, r, 1, 0);
    for (short i = 0; i < N; i++) {
        cflow.addEdge(2 * i + 3, 2 * i + 4, 1, 0), cflow.addEdge(2 * i + 4, t, 1, -point[i].P);
        if (std::abs(point[i].X - (int)L) <= V * point[i].T) { cflow.addEdge(l, 2 * i + 3, 1, 0); }
        if (std::abs(point[i].X - (int)R) <= V * point[i].T) { cflow.addEdge(r, 2 * i + 3, 1, 0); }
    }
    for (short i = 0; i < N; i++) {
        for (short j = i + 1; j < N; j++) {
            if (std::abs(point[i].X - point[j].X) <= V * (point[j].T - point[i].T)) { cflow.addEdge(2 * i + 4, 2 * j + 3, 1, -point[i].P); }
        }
    }
    point.clear(), point.shrink_to_fit();
    std::cout << -PrimalDual<int, PotDAG>(cflow, s, t, (char)2).second << std::endl;

    return 0;
}
accuracy: 1
time_ms: 1000
memory_kb: 241684
final_rank: 10

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
//#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

#define HUGE_NUM 10000000000
#define NUM 6050

typedef pair<ll,ll> P;

struct Edge{
    Edge(int arg_to,ll arg_capacity,ll arg_cost,int arg_rev_index){
        to = arg_to;
        capacity = arg_capacity;
        cost = arg_cost;
        rev_index = arg_rev_index;
    }

    int to,rev_index;
    ll capacity,cost;
};

struct Info{
    void set(int arg_x,int arg_appear_time,ll arg_value){
        x = arg_x;
        appear_time = arg_appear_time;
        value = arg_value;
    }
    bool operator<(const struct Info & arg) const{
        return appear_time < arg.appear_time;
    }
    int x,appear_time;
    ll value;
};

int N,speed;
int V;
vector<Edge> G[NUM];
ll h[NUM];
ll dist[NUM];
int pre_node[NUM],pre_edge[NUM];
int index_IN[NUM],index_OUT[NUM];
int in_num[NUM];
bool visited[NUM];
Info LEFT,RIGHT,info[NUM];


void add_edge(int from,int to,ll capacity,ll cost){
    G[from].push_back(Edge(to,capacity,cost,G[to].size()));
    G[to].push_back(Edge(from,0,-cost,G[from].size()-1));
}


ll min_cost_flow(int source,int sink,ll flow){
    ll ret = 0;
    for(int i = 0; i < V; i++){
        h[i] = HUGE_NUM;
        in_num[i] = 0;
    }

    h[source] = 0;

    for(int i = 0; i < V; i++){
        for(ll k = 0; k < G[i].size(); k++){
            if(G[i][k].capacity == 0)continue;

            in_num[G[i][k].to]++;
        }
    }

    queue<int> TOPO;
    for(int i = 0; i < V; i++){

        if(in_num[i] == 0){
            TOPO.push(i);
        }
    }

    int tmp_node;

    while(!TOPO.empty()){
        tmp_node = TOPO.front();
        TOPO.pop();

        for(int i = 0; i < G[tmp_node].size(); i++){
            if(G[tmp_node][i].capacity <= 0)continue;

            h[G[tmp_node][i].to] = min(h[G[tmp_node][i].to],h[tmp_node]+G[tmp_node][i].cost);

            in_num[G[tmp_node][i].to]--;
            if(in_num[G[tmp_node][i].to] == 0){
                TOPO.push(G[tmp_node][i].to);
            }
        }
    }

    while(flow > 0){

        for(int i = 0; i < V; i++)dist[i] = HUGE_NUM;
        dist[source] = 0;

        for(int i = 0; i < V; i++)visited[i] = false;

        while(true){

            tmp_node = -1;

            for(ll i = 0; i < V; i++){
                if(visited[i] == false && (tmp_node == -1 || dist[tmp_node] > dist[i])){
                    tmp_node = i;
                }
            }

            if(tmp_node == -1)break;

            visited[tmp_node] = true;

            for(int i = 0; i < G[tmp_node].size(); i++){
                Edge &e = G[tmp_node][i];
                if(e.capacity == 0 || dist[e.to] <= dist[tmp_node]+e.cost+h[tmp_node]-h[e.to])continue;
                dist[e.to] = dist[tmp_node]+e.cost+h[tmp_node]-h[e.to];
                pre_node[e.to] = tmp_node;
                pre_edge[e.to] = i;

            }
        }

        if(dist[sink] == HUGE_NUM){
            return -1;
        }

        for(int node_id = 0; node_id < V; node_id++)h[node_id] += dist[node_id];

        ll tmp_flow = flow;

        for(int node_id = sink; node_id != source; node_id = pre_node[node_id]){

            tmp_flow = min(tmp_flow,G[pre_node[node_id]][pre_edge[node_id]].capacity);
        }
        flow -= tmp_flow;
        ret += tmp_flow*h[sink];

        for(int node_id = sink; node_id != source; node_id = pre_node[node_id]){
            Edge &e = G[pre_node[node_id]][pre_edge[node_id]];
            e.capacity -= tmp_flow;
            G[node_id][e.rev_index].capacity += tmp_flow;
        }
    }
    return ret;
}


int main(){

    scanf("%d %d %d %d",&N,&speed,&LEFT.x,&RIGHT.x);

    for(int i = 0; i < N; i++){

        scanf("%d %d %d",&info[i].x,&info[i].appear_time,&info[i].value);
    }
    sort(info,info+N);

    int source = 0,sink = 1,first_left = 2,first_right = 3,index = 4;

    for(int i = 0; i < N; i++){

        index_IN[i] = index++;
    }
    for(int i = 0; i < N; i++){

        index_OUT[i] = index++;
        add_edge(index_OUT[i],sink,1,0);
    }
    for(ll i = 0; i < N; i++){

        add_edge(index_IN[i],index_OUT[i],1,-info[i].value);
    }

     add_edge(source,first_left,1,0);
    add_edge(first_left,sink,1,0);

    for(int i = 0; i < N; i++){

        if(abs(info[i].x-LEFT.x) <= speed*info[i].appear_time){

            add_edge(first_left,index_IN[i],1,0);
        }
    }

    add_edge(source,first_right,1,0);
    add_edge(first_right,sink,1,0);

    for(int i = 0; i < N; i++){

        if(abs(info[i].x-RIGHT.x) <= speed*info[i].appear_time){

            add_edge(first_right,index_IN[i],1,0);
        }
    }

    for(int i = 0; i < N-1; i++){
        for(int k = i+1; k < N; k++){
            if(abs(info[k].x-info[i].x) <= speed*(info[k].appear_time-info[i].appear_time)){

                add_edge(index_OUT[i],index_IN[k],1,0);
            }
        }
    }

    add_edge(source,sink,2,0);

    V = index;

    ll ans = min_cost_flow(source,sink,2);

    printf("%lld\n",-ans);

    return 0;
}
accuracy: 1
time_ms: 340
memory_kb: 256348
final_rank: 5