#include<cstdio>
#include<iostream>
#include<algorithm>
#include<utility>
#include<vector>
#include<queue>
#include<functional>
#include<map>
#include<set>
#include<cstring>
#include<string>
#include<stack>
#include<math.h>
#include<stdlib.h>
using namespace std;
#define int long long
//#define double long double
typedef pair<int, int> pii;
typedef pair<pii, int> ppi;
typedef pair<int, pii > pip;
typedef pair<pii, pii > piipii;
typedef pair<double, double> pdd;
typedef pair<int, char> pic;
typedef priority_queue<pii, vector<pii>, greater<pii> > RPQ;
#define all(vec) vec.begin(), vec.end()
#define mk make_pair
#define INF (1ll << 60)
//#define INFL (1ll << 60)
#define mod 1000000007
#define se second
#define fi first

template<typename T> class LazySegmentTree {
    int n, sz;
    vector<T> dat, Lazy;

    void eval(int k){//ノードkの値を更新して遅延配列を伝播
        dat[k] = min(dat[k], Lazy[k]);//ココ
        if(Lazy[k] < INF){
            if(k < n - 1) {
                Lazy[2 * k + 1] = min(Lazy[2 * k + 1], Lazy[k]);
                Lazy[2 * k + 2] = min(Lazy[2 * k + 2], Lazy[k]);
            }
            Lazy[k] = INF;
        }
    }

public:
    LazySegmentTree(const vector<T> &v) : sz((int)v.size()) {
        //nは元配列の要素数以上で最小の二冪
        //datは[n-1, 2n-1]が元の配列に対応　最下段より上段の要素数がn-1
        n = 1;
        while(n < sz)n *= 2;
        dat.resize(2 * n - 1, INF);//ノードを単位元で初期化
        Lazy.resize(2 * n - 1, INF);//遅延配列を0で初期化

        for(int i = 0; i < sz; i++){
            dat[i + n - 1] = v[i];//元配列に対応するノードを初期化
        }
        for(int i = n - 2; i >= 0; i--){
            dat[i] = min(dat[2 * i + 1], dat[2 * i + 2]);//下から上になめて更新
        }
    }

    //[a,b)にxを一様加算
    //今見てるノードのインデックス:k  それに対応する元配列の区間[l,r)
    //ノードの値を更新

    void add(int a, int b, T x, int k = 0, int l = 0, int r = -1){
        if(r < 0)r = n;
        eval(k);//ココ
        if(r <= a || b <= l){//更新区間にふくまれない
            return;
        }
        if(a <= l && r <= b){//更新区間に完全に含まれる
            Lazy[k] = min(Lazy[k], x);
            eval(k);
        }
        else {//一部更新区間を含む
            add(a, b, x, 2 * k + 1, l, (l + r) / 2);
            add(a, b, x, 2 * k + 2, (l + r) / 2, r);
            if(k < n - 1){//ココ
                dat[k] = min(dat[2 * k + 1], dat[2 * k + 2]);
            }
        }
        
    }

    //[a,b)のminを求める
    T query(int a, int b, int k = 0, int l = 0, int r = -1){
        if(r < 0)r = n;
        if(r <= a || b <= l){
            return INF;//目的の区間を含まないので単位元を返す
        }

        eval(k);
        if(a <= l && r <= b){//遅延配列を更新してノードの値を返す
            return dat[k];
        }
        else {//左右に配って帰ってきた二つのminを返す
            T vl = query(a, b, 2 * k + 1, l, (l + r) / 2);
            T vr = query(a, b, 2 * k + 2, (l + r) / 2, r);
            return min(vl, vr);
        }
    }
};

int N, M;
struct LRC{
    int l, r, c;
};
LRC lrc[100100];

signed main(){
    cin >> N >> M;
    for(int i = 0; i < M; i++){
        int a, b, c;
        cin >> a >> b >> c;
        a--, b--;
        lrc[i].l = a;
        lrc[i].r = b;
        lrc[i].c = c;
    }
    sort(lrc, lrc + M, [](LRC& a, LRC& b){return a.l < b.l;});
    vector<int> V;
    V.resize(N, INF);
    V[0] = 0;
    LazySegmentTree<int> seg(V);
    for(int i = 0; i < M; i++){
        LRC C = lrc[i];
        int mi = seg.query(C.l, C.r + 1);
        int cost = mi + C.c;
        seg.add(C.l, C.r + 1, cost);
    }
    int ans = seg.query(N - 1, N);
    if(ans >= INF){
        cout << -1 << endl;
    }
    else {
        cout << ans << endl;
    }
    
    return 0;
}

/*

*/

Measured memory_bytes: 7424