#include <bits/stdc++.h>

#define debug(x) cerr << #x << ": " << x << endl
#define debugArray(x, n)                                                       \
    for(long long hoge = 0; (hoge) < (n); ++(hoge))                            \
    cerr << #x << "[" << hoge << "]: " << x[hoge] << endl
using namespace std;

using ll = long long;
const ll INF = INT_MAX;

template <typename M> class LazySegmentTree {
  private:
    using T = typename M::T;
    using E = typename M::E;
    int height, n;
    vector<T> dat;
    vector<E> laz;
    inline T reflect(int k) {
        return laz[k] == M::ei() ? dat[k] : M::g(dat[k], laz[k]);
    }
    inline void eval(int k) {
        if(laz[k] == M::ei())
            return;
        laz[(k << 1) | 0] = M::h(laz[(k << 1) | 0], laz[k]);
        laz[(k << 1) | 1] = M::h(laz[(k << 1) | 1], laz[k]);
        dat[k] = reflect(k);
        laz[k] = M::ei();
    }
    inline void thrust(int k) {
        for(int i = height; i; i--)
            eval(k >> i);
    }
    inline void recalc(int k) {
        while(k >>= 1)
            dat[k] = M::f(reflect((k << 1) | 0), reflect((k << 1) | 1));
    }
    void init() {
        for(int i = n - 1; i >= 1; i--)
            dat[i] = M::f(dat[i << 1 | 0], dat[i << 1 | 1]);
    }
    void init(const vector<T> &dat_) {
        for(int i = 0; i < (int)dat_.size(); i++)
            dat[i + n] = dat_[i];
        init();
    }

  public:
    LazySegmentTree() {}
    LazySegmentTree(int n_)
        : height(ceil(log2(n_))), n(1 << height), dat(n * 2, M::ti()),
          laz(n * 2, M::ei()) {}
    LazySegmentTree(int n_, T v1)
        : height(ceil(log2(n_))), n(1 << height), dat(n * 2, v1),
          laz(n * 2, M::ei()) {
        init();
    }
    LazySegmentTree(const vector<T> &dat_)
        : height(ceil(log2(dat_.size()))), n(1 << height), dat(n * 2, M::ti()),
          laz(n * 2, M::ei()) {
        init(dat_);
    }
    void update(int a, int b, E x) {
        thrust(a += n);
        thrust(b += n - 1);
        for(int l = a, r = b + 1; l < r; l >>= 1, r >>= 1) {
            if(l & 1)
                laz[l] = M::h(laz[l], x), l++;
            if(r & 1)
                --r, laz[r] = M::h(laz[r], x);
        }
        recalc(a);
        recalc(b);
    }
    void set_val(int a, T x) {
        thrust(a += n);
        dat[a] = x;
        laz[a] = M::ei();
        recalc(a);
    }
    T query(int a, int b) {
        thrust(a += n);
        thrust(b += n - 1);
        T vl = M::ti(), vr = M::ti();
        for(int l = a, r = b + 1; l < r; l >>= 1, r >>= 1) {
            if(l & 1)
                vl = M::f(vl, reflect(l++));
            if(r & 1)
                vr = M::f(reflect(--r), vr);
        }
        return M::f(vl, vr);
    }
    T operator[](const int k) { return query(k, k + 1); }
};

struct RupdqRminq {
    using T = ll;
    using E = ll;
    static T ti() { return INT_MAX; }
    static E ei() { return INF; }
    static T f(const T &l, const T &r) { return min(l, r); }
    static T g(const T &l, const E &r) { return r == ei() ? l : r; }
    static E h(const E &l, const E &r) { return r == ei() ? l : r; }
};

signed main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    ll N, M;
    cin >> N >> M;
    tuple<ll, ll, ll> LRC[M];
    for(int i = 0; i < M; i++) {
        ll L, R, C;
        cin >> L >> R >> C;
        L--;
        R--;
        LRC[i] = {L, R, C};
    }
    sort(LRC, LRC + M);
    LazySegmentTree<RupdqRminq> seg(N);
    seg.set_val(0, 0);
    for(ll i = 0; i < M; i++) {
        ll L, R, C;
        tie(L, R, C) = LRC[i];
        ll low = L, high = R + 1;
        ll v = seg[L] + C;
        while(high - low > 1) {
            ll mid = (low + high) / 2;
            if(seg[mid] < v) {
                low = mid;
            } else {
                high = mid;
            }
        }
        if(high < R + 1)
            seg.update(high, R + 1, v);
    }
    ll ans = seg[N - 1];
    if(ans == INF)
        ans = -1;
    cout << ans << endl;
    return 0;
}
