#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
using namespace std;
namespace mp = boost::multiprecision;
#define rep(i,n) for (int i=0; i<(int)(n); ++i)
#define rep0(i,n) for (int i=0; i<=(int)(n); ++i)
#define rep1(i,n) for (int i=1; i<=(int)(n); ++i)
#define rrep(i,n) for (int i=(int)(n)-1; i>=0; --i)
#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
using ll = long long;
using vi = vector<int>;
using vl = vector<ll>;
using Graph = vector<vi>;
using llGraph = vector<vl>;
using vb = vector<bool>;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
const int MOD = 1e9+7;
const int MOD2 = 998244353;
const double EPS = 1e-9;

template<typename T>
struct is_vector : false_type{};

template<typename T>
struct is_vector<vector<T>> : true_type{};

template<typename T>
ostream &operator << (ostream &ostr, const vector<T> &vec) {
  if (vec.empty()) {
    return ostr;
  }
  ostr << vec.front();
  for (auto itr = ++vec.begin(); itr != vec.end(); ++itr) {
    if (is_vector<T>()) ostr << "\n" << *itr;
    else ostr << ' ' << *itr;
  }
  return ostr;
}

template<typename T>
bool CompareBySecond(pair<T, T> a, pair<T, T> b) {
  if (a.second != b.second) {
    return a.second < b.second;
  } else {
    return a.first < b.first;
  }
}

template<typename T>
bool CompareBySlope(pair<T, T> a, pair<T, T> b) {
// counterclockwise from 12 o'clock direction
  if (a.first * b.first < 0) {
    return a.first < b.first;
  }
  if (a.first == 0) {
    if (a.second >= 0) {
      return true;
    }
    return a.first < b.first;
  }
  if (b.first == 0) {
    if (b.second >= 0) {
      return false;
    }
    return a.first < b.first;
  }
  return a.second * b.first < a.first * b.second;
}

template<typename T>
T GCD(T a, T b) {
  T c = a % b;
  while (c != 0) { a = b; b = c; c = a % b; }
  return b;
}


/* -------- <templates end> -------- */


template<typename Monoid>
struct SegmentTree {
  using F = function<Monoid(Monoid, Monoid)>;

  int sz;
  vector<Monoid> seg;

  const F f;
  const Monoid M1;

  SegmentTree(int n, const F f, const Monoid &M1) : f(f), M1(M1) {
    sz = 1;
    while (sz < n) sz <<= 1;
    seg.assign(2*sz, M1);
  }

  void set(int k, const Monoid &x) {
    seg[k+sz] = x;
  }

  void build() {
    for (int k = sz-1; k>0; --k) {
      seg[k] = f(seg[2*k+0], seg[2*k+1]);
    }
  }

  void update(int k, const Monoid &x) {
    k += sz;
    seg[k] = x;
    while (k >>= 1) {
      seg[k] = f(seg[2*k+0], seg[2*k+1]);
    }
  }

  Monoid query(int a, int b) {
    Monoid L = M1, R = M1;
    for (a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
      if (a & 1) L = f(L, seg[a++]);
      if (b & 1) R = f(seg[--b], R);
    }
    return f(L, R);
  }

  Monoid operator[](const int &k) const {
    return seg[k+sz];
  }
};

struct edge {
  int from, to, cost;
  void input(int &a, int &b, int &c) {
    from = a; to = b; cost = c;
  }
};

void solve() {
  int n, m; cin >> n >> m;
  vector<edge> G(m);
  rep(i,m) {
    int l, r, c;
    cin >> l >> r >> c;
    --l; --r;
    G[i].input(l, r, c);
  }

  sort(ALL(G), [](const edge &a, const edge &b) {
    return a.from < b.from;
  });

  const ll INFTY = 1e15;
  SegmentTree<ll> seg(n, [](ll a, ll b) { return min(a, b); } , INFTY);
  seg.set(0, 0);
  seg.build();

  for (auto &e : G) {
    ll cost = seg.query(e.from, e.to) + e.cost;
    if (cost < seg[e.to]) seg.update(e.to, cost);
  }

  cout << (seg[n-1] == INFTY ? -1 : seg[n-1]) << endl;
}


/* -------- <programs end> -------- */


int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(12);
  solve();
  return 0;
}


Measured memory_bytes: 3456