#include <bits/stdc++.h>
using namespace std;
#define repr(i,a,b) for(int i=a;i<b;i++)
#define rep(i,n) for(int i=0;i<n;i++)
#define reprrev(i,a,b) for(int i=b-1;i>=a;i--) // [a, b)
#define reprev(i,n) reprrev(i,0,n)
typedef long long ll;
typedef unsigned long long ull;
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

/* attention
    long longのシフト演算には気をつけよう
    タイポした時のデバッグが死ぬほどきつくなるので変数名は最低3字くらい使った方がいいかも
    sizeは(int)とキャストしよう
    cin.tie(0);
    ios::sync_with_stdio(false);<- これら、printfとかと併用しない方が良さそう

*/

const ll mod = 998244353;

void chmod(ll &M){
    if(M >= mod) M %= mod;
    else if(M < 0){
        M += (abs(M)/mod + 1)*mod;
        M %= mod;
    }
}

ll modpow(ll x, ll n){
    if(n==0) return 1;
    ll res=modpow(x, n/2);

    if(n%2==0) return res*res%mod;
    else return res*res%mod*x%mod;
}

int getl(int i, int N) { return i==0? N-1:i-1; };
int getr(int i, int N) { return i==N-1? 0:i+1; };


// 線分 ab の偏角 返り値は[-π, π]
double argument(const pair<double, double> &a, const pair<double, double> &b){
    double ax=a.first, ay=a.second, bx=b.first, by=b.second;
    return atan2(by-ay, bx-ax);
}

/* <-----------------------------------------------------------------------------------> */
/* <-----------------------------------------------------------------------------------> */
/* <-----------------------------------------------------------------------------------> */
/* <-----------------------------------------------------------------------------------> */


// cf https://www.creativ.xyz/segment-tree-abstraction-979/
template < class T > 
class SegTree{                      
    int n;                          // 葉の数
    vector<T> data;                 // データを格納するvector
    T def;                          // 初期値かつ単位元
    function<T(T, T)> operation;    // 区間クエリで使う処理
    function<T(T, T)> update;       // 点更新で使う処理


    // 区間[a, b)の総和。ノード k=[l, r) に着目している。
    T _query(int a, int b, int k, int l, int r){
        if(r <= a || b <= l) return def;
        if(a <= l && r <= b) return data[k];
        else{
            T c1 = _query(a, b, 2*k+1, l, (l+r)/2);
            T c2 = _query(a, b, 2*k+2, (l+r)/2, r);
            return operation(c1, c2);
        }

    }

    public:
        // _n:必要サイズ, _def:初期値かつ単位元, _operaotion:クエリ関数
    // _update:更新関数
        SegTree(size_t _n, T _def, function<T(T, T)> _operation, function<T(T, T)> _update)
            : def(_def), operation(_operation), update(_update) {
            n = 1;
            while(n < _n) n *= 2;
            data = vector<T>(2*n-1, def);
        }

        // [a, b) の区間クエリを実行
        T query(int a, int b){
            return _query(a, b, 0, 0, n);
        }

        // 場所 i(0-indexed) の値を x で更新
        void change(int i, T x){
            i += n-1;
            // 点加算なら [](T d, T x){ return d+x; }, 点更新なら [](T d, T x){ return x; }
            data[i] = update(data[i], x);
            while(i > 0){
                i = (i-1)/2;
                data[i] = operation(data[i*2+1], data[i*2+2]); 
            }
        }

        T operator[](int i){ return data[i+n-1]; }
};

using T = tuple<ll, ll, ll>;

const ll inf = 1LL<<59;

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    int n, m; cin >> n >> m;
    vector<T> rlc(m);
    rep(i, m){
        int l, r, c; cin >> l >> r >> c;
        rlc[i] = make_tuple(r, l, c);
    }
    sort(rlc.begin(), rlc.end());

    SegTree<ll> seg(n+5, inf, [](ll  a, ll b){return min(a, b); }, [](ll a, ll b){ return b; });
    seg.change(1, 0);

    rep(i, m){
        int r, l;
        ll c;
        tie(r, l, c) = rlc[i];
        ll tmp = seg.query(l, r);
        if(seg[r] > tmp+c) seg.change(r, tmp+c);
    }

    if(seg[n] == inf) cout << -1 << endl;
    else cout << seg[n] << endl;

    return 0;
}

Measured memory_bytes: 4608