#include <bits/stdc++.h>

template <typename T,typename E>
struct LazySegmentTree{
private:
    typedef std::function<T(T,T)> F;
    typedef std::function<T(T,E)> G;
    typedef std::function<E(E,E)> H;
    typedef std::function<E(E,int)> P;
    int n;
    F cal;//function for merge
    G upd;//function for update
    H ecal;//function for evaluate
    P rcal;//function for range calculate
    std::vector<T> init;
    T initv;
    E opinit;
    std::vector<T> node;
    std::vector<E> lazy;
public:
    explicit LazySegmentTree(//特定の要素で初期化する場合
            int sz,
            F cal,
            G upd,
            H ecal,
            P rcal=[](E a,int b){return a;},
            T initv=std::numeric_limits<long long>::max(),
            E opinit=0
    ):
    cal(cal),
    upd(upd),
    ecal(ecal),
    rcal(rcal),
    initv(initv),
    opinit(opinit)
    {
        n=1;
        while(n<sz)n=n*2;
        node.resize(static_cast<unsigned int>(2 * n - 1), initv);
        for (int i = 0; i <sz ; ++i) node[i+n-1]=(T)0;
        for (int i = n-2; i >= 0 ; --i) node[i]=cal(node[2*i+1],node[2*i+2]);

        lazy.resize(static_cast<unsigned int>(2 * n - 1), opinit);
        for (int i = 0; i <sz ; ++i) lazy[i+n-1]=opinit;
        for (int i = n-2; i >= 0 ; --i) lazy[i]=ecal(lazy[2*i+1],lazy[2*i+2]);
    }

    void update(int p,int q,E val,int k=0,int l=0,int r=-1){//[p,q):0-indexed
        if(r<0)r=n;
        eval(k,r-l);
        if(r<=p||l>=q)return;
        if(p<=l&&r<=q){
            lazy[k]=ecal(lazy[k],val);
            eval(k,r-l);
        }
        else{
            update(p,q,val,2*k+1,l,(l+r)/2);
            update(p,q,val,2*k+2,(l+r)/2,r);
            node[k]=cal(node[2*k+1],node[2*k+2]);
        }
    }

    T query(int p,int q,int k=0,int l=0,int r=-1){//[p,q):0-indexed
        if(r<0)r=n;
        if(r<=p||l>=q)return initv;

        eval(k,r-l);
        if(p<=l&&r<=q)return node[k];
        T vl=query(p,q,2*k+1,l,(l+r)/2);
        T vr=query(p,q,2*k+2,(l+r)/2,r);
        return cal(vl,vr);
    }

    void eval(int k,int len){//k:0-indexed
        if(lazy[k]==opinit)return;
        node[k]=upd(node[k],rcal(lazy[k],len));
        if(k<n-1){
            lazy[2*k+1]=ecal(lazy[2*k+1],lazy[k]);
            lazy[2*k+2]=ecal(lazy[2*k+2],lazy[k]);
        }
        lazy[k]=opinit;
    }
};

using namespace std;
using ll = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    ll n,m,k,d,s;
    cin>>n>>m>>k>>d>>s;
    vector<pair<ll,pair<ll,ll>>> data;
    int ind=0;
    map<ll,int> zatu;
    for(int i = 0;i < m;++i) {
        ll a,b,c;
        cin>>a>>b>>c;
        if(zatu.find(c)==zatu.end()){
            zatu[c]=ind;
            ++ind;
        }
        data.emplace_back(a,make_pair(b,c));
    }
    if(ind<n){
        zatu[-1]=ind;
        ++ind;
    }
    sort(data.begin(),data.end());

    LazySegmentTree<ll,ll> st(
        ind,
        [](ll a,ll b)->ll{return min(a,b);},
        [](ll a,ll b)->ll{return max(a-b,0LL);},
        [](ll a,ll b)->ll{return a+b;}
    );

    ll szt=s+d;
    ll pszt=0;
    while(k>0&&szt<data[0].first){
        --k;
        szt+=d;
    }

    st.update(zatu[data[0].second.second],zatu[data[0].second.second]+1,-data[0].second.first);
    pszt=data[0].first;
    for(int i = 1;i < m;++i) {
        while(k>0&&szt<data[i].first){
            --k;
            st.update(0,ind,szt-pszt);
            pszt=szt;
            szt+=st.query(0,ind);
            szt+=d;
        }
        if(k<=0)break;

        st.update(0,ind,data[i].first-pszt);
        st.update(zatu[data[i].second.second],zatu[data[i].second.second]+1,-data[i].second.first);
        pszt=data[i].first;
    }
    while(k>0){
        --k;
        st.update(0,ind,szt-pszt);
        pszt=szt;
        szt+=st.query(0,ind);
        szt+=d;
    }

    cout<<szt-d-s<<endl;

    return 0;
}



Measured memory_bytes: 15408