#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = LLONG_MAX / 10;
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] = tuple<ll, ll, ll>(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];
    if (v == INF) {
      break;
    }
    v += 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;
}
