#include <iostream>
#include <fstream>
#include <cmath>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <unordered_set>
#include <bitset>
#include <limits>
#include <algorithm>

#define MOD_BIG 1000000007
#define MOD_BIG2 998244353
using std::string;
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
using ll = long long;
using pint = std::pair<int, int>;
using pll = std::pair<ll, ll>;
using std::vector;

#define FOR(i, begin, end) for(int i=(begin),i##_end_=(end);i<i##_end_;i++)
#define IFOR(i, begin, end) for(int i=(end)-1,i##_begin_=(begin);i>=i##_begin_;i--)
#define REP(i, n) FOR(i,0,n)
#define IREP(i, n) IFOR(i,0,n)

//////////////////////////////////////

enum Status {
    Not = 0,
    Now,
    End,
};

template<typename T>
struct Edge {
    int to;
    int from;
    T weight;
    Edge(int from, int to, T weight) : from(from), to(to), weight(weight) {}
};

template<typename T, typename D>
struct Graph {
    int n;
    vector<vector<Edge<T>>> g;
    vector<D> data;
    vector<Status> s;
    
    Graph(int N) : n(N), g(N+1), data(N+1), s(N+1) {}
    
    void add_edge(int from, Edge<T> e) {
        g[from].push_back(e);
    }
    void add_edge(int from, int to, T weight) {
        g[from].push_back(Edge<T>(from, to, weight));
    }
    void set_data(int node, D value) {
        data[node] = value;
    }
    
    //幅優先探索による最短経路
    //weightが全て同一の場合線形
    std::pair< vector<T>, vector<vector<Edge<T>>> > bfs_spp(int start) {
        vector<T> d(n+1, -1);
        vector<vector<Edge<T>>> route(n+1);
        std::queue<int> q;
        d[start] = 0;
        q.push(start);
        while(!q.empty()) {
            int v = q.front();
            q.pop();
            
            for (auto e: g[v]) {
                if (d[e.to] != -1 && d[e.to] != 0) {
                    //到達済み
                    continue;
                }
                d[e.to] = d[e.from] + 1;
                auto tmp = route[e.from];
                tmp.push_back(e);
                route[e.to] = tmp;
                q.push(e.to);
            }
        }
        return std::make_pair(d, route);
    }
    
    //ダイクストラ法
    //weightが非負の場合の最短経路
    //経路が存在しない場合、INFが返るのでオーバーフローに注意
    std::pair< vector<T>, vector<vector<Edge<T>>> > dijkstra(int start){
        using P = std::pair<T, int>;
        std::priority_queue<P, vector<P>, std::greater<P>> que;
        T T_MAX = std::numeric_limits<T>::max();
        vector<T> d(n+1, T_MAX);
        vector<vector<Edge<T>>> route(n+1);
        d[start] = 0;
        que.push(P((T)0, start));
        while(!que.empty()){
            P p = que.top();
            que.pop();
            int v = p.second;
            if(d[v] < p.first) continue;
            for(Edge<T> e : g[v]){
                if(d[e.to] > d[v] + e.weight){
                    d[e.to] = d[v] + e.weight;
                    que.push(P(d[e.to], e.to));
                }
            }
        }
        return std::make_pair(d, route);
    }
    
    //ベルマン-フォード法
    //weightを負を含む距離として最短経路を求める
    //無限ループが存在する場合、trueを1つ目に返す
    std::pair<bool, vector<T>> bellman_ford(int start) {
        T T_INF = std::numeric_limits<T>::max();
        vector<T> d(n+1, T_INF);
        vector<Edge<T>> E;
        for (int i = 0; i <= n; i++) {
            for (auto e: g[i]) {
                E.push_back(e);
            }
        }
        d[start] = 0;
        for (int i = 0; i <= n; i++) {
            for (auto e: E) {
                if (d[e.from] != T_INF && d[e.from] + e.weight < d[e.to]) {
                    //最初or別のstartからe.toへの最短路を発見
                    d[e.to] = d[e.from] + e.weight;
                    //std::cout << "new route find, to: " << e.to << ", distance: " << d[e.to] << std::endl;
                    if (i == n) {
                        //もう全ての辺はチェック済みのはずなのにまだ更新がある：無限ループあり
                        return std::make_pair(true, d);
                    }
                }
            }
        }
        return std::make_pair(false, d);
    }
    
    //あるノードに到達できるか
    //逆方向はグラフ自体逆で構成することで可能
    vector<bool> can_reach_from(int start) {
        vector<bool> reached(n+1, false);
        dfs_reach_from(start, reached);
        return reached;
    }
    void dfs_reach_from(int now, vector<bool> &reached) {
        if (reached[now]) return;
        reached[now] = true;
        for (auto e: g[now]) {
            dfs_reach_from(e.to, reached);
        }
    }
    
    //出力
    void print() {
        for (auto v: g) {
            for (auto e: v) {
                std::cout << e.from << "-(" << e.weight << ")->" << e.to << ", ";
            }
            std::cout << std::endl;
        }
    }
};

//////////////////////////////////////

int main() {
    
    int N, M;
    cin >> N >> M;
    Graph<ll, ll> g(N);
    FOR(i, 1, N) {
        g.add_edge(i+1, i, 0);
    }
    REP(i, M) {
        int l, r;
        ll c;
        cin >> l >> r;
        cin >> c;
        g.add_edge(l, r, c);
    }
    auto res = g.dijkstra(1);
    auto ans = res.first[N];
    if (ans == std::numeric_limits<ll>::max()) {
        cout << -1 << endl;
    } else {
        cout << ans << endl;
    }
    
    return 0;
}


Measured memory_bytes: 16116