#include <bits/stdc++.h>
#define show(x) cerr << #x << " = " << x << endl
using namespace std;
using ll = long long;
template <typename T>
constexpr T INF = numeric_limits<T>::max() / 16;
template <typename Monoid>
class SegmentTree
{
private:
    static constexpr int sz(const int n)
    {
        int ans = 1;
        for (; n > ans; ans <<= 1) {}
        return ans;
    }

public:
    using BaseMonoid = Monoid;
    using T = typename Monoid::T;

    SegmentTree(const int n) : data_num(n), half(sz(n)), value(half << 1, Monoid::id()) {}
    template <typename InIt>
    SegmentTree(const InIt first, const InIt last) : data_num(distance(first, last)), half(sz(data_num)), value(half << 1, Monoid::id())
    {
        copy(first, last, value.begin() + half);
        for (int i = half - 1; i >= 1; i--) { up(i); }
    }
    T get(const int a) const
    {
        assert(0 <= a and a < data_num);
        return value[a + half];
    }
    void set(int a, const T& val)
    {
        assert(0 <= a and a < data_num);
        value[a += half] = val;
        while (a >>= 1) { up(a); }
    }
    T accumulate(int L, int R) const
    {
        assert(0 <= L and L < R and R <= data_num);
        T accl = Monoid::id(), accr = Monoid::id();
        for (L += half, R += half; L < R; L >>= 1, R >>= 1) {
            if (L & 1) { accl = acc(accl, value[L++]); }
            if (R & 1) { accr = acc(value[--R], accr); }
        }
        return acc(accl, accr);
    }
    template <typename F, typename QueryOp, typename AccOp>
    F query(int L, int R, const QueryOp& query_op, const AccOp& acc_op) const
    {
        assert(0 <= L and L < R and R <= data_num);
        constexpr F id = F{};  // Fの単位元(AccOpについての)
        F accl = id, accr = id;
        for (L += half, R += half; L < R; L >>= 1, R >>= 1) {
            if (L & 1) { accl = acc_op(accl, query_op(value[L++])); }
            if (R & 1) { accr = acc_op(query_op(value[--R]), accr); }
        }
        return acc_op(accl, accr);
    }
    template <typename Pred>
    int partitionPoint(const int L, const int R, const Pred& pred) const
    {
        auto prec = fix([&](auto&& self, const int index, const int left, const int right, const T& offset) -> pair<T, int> {
            if (right <= L or R <= left or pred(acc(offset, value[index]))) { return {Monoid::id(), -1}; }
            if (index >= half) { return {value[index], index - half}; }
            const pair<T, int> lans = self(self, index << 1, left, (left + right) >> 1, offset);
            if (lans.second != -1) { return lans; }
            return self(self, index << 1 | 1, (left + right) >> 1, right, acc(offset, lans.first));
        });
        const int ans = prec(1, 0, half, Monoid::id()).second;
        return ans == -1 ? R : ans;
    }

    vector<T> data() const { return vector<T>(value.begin() + half, value.begin() + half + data_num); }
    void debug() const
    {
        for (int l = 1; l < (half << 1); l <<= 1) {
            for (int i = l; i < (l << 1); i++) { cout << value[i] << ","; }
            cout << endl;
        }
    }

private:
    void up(const int i) { value[i] = acc(value[i << 1], value[i << 1 | 1]); }
    const int data_num;  // Num of valid data on leaves.
    const int half;
    vector<T> value;
    const Monoid acc{};
};

template <typename T>
ostream& operator<<(ostream& os, const SegmentTree<T>& seg)
{
    os << "[";
    for (const auto e : seg.data()) { os << e << ","; }
    return (os << "]" << endl);
}

struct Min
{
    using T = ll;
    T operator()(const T& a, const T& b) const { return min(a, b); }
    static constexpr T id() { return INF<T>; }
};
template <typename T, typename A>
inline ostream& operator<<(ostream& os, const vector<T, A>& v)
{
    os << "[";
    for (const auto& p : v) { os << p << ","; }
    return (os << "]" << endl);
}

int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    ll N, M, K, D, S;
    cin >> N >> M >> K >> D >> S;
    if (N > M) {
        for (int i = 0, d = 0; i < M; i++) { cin >> d >> d >> d; }
        cout << D * K << endl;
    } else {
        vector<ll> a(M), b(M), c(M);
        for (int i = 0; i < M; i++) { cin >> a[i] >> b[i] >> c[i]; }
        ll ans = S + D;
        vector<ll> zero(N, 0);
        SegmentTree<Min> seg(zero.begin(), zero.end());
        int pos = 0;
        for (int i = 0; i < K; i++) {
            for (; pos < M and a[pos] <= ans; pos++) { seg.set(c[pos] - 1, max(seg.get(c[pos] - 1), a[pos]) + b[pos]); }
            ans = max(ans, seg.accumulate(0, N)) + D;
        }
        cout << ans - S - D << endl;
    }
    return 0;
}



Measured memory_bytes: 8044