#include <bits/stdc++.h>
using namespace std;
using pii = pair<int, int>;
using ll = long long;
template <class T>
bool set_min(T &a, const T &b) {
  return a > b ? a = b, true : false;
}
template <class T>
bool set_max(T &a, const T &b) {
  return a < b ? a = b, true : false;
}
template <class T>
istream &operator>>(istream &is, vector<T> &v) {
  for (T &a : v) is >> a;
  return is;
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  for (const T &t : v) os << "\t" << t;
  return os << endl;
}
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &v) {
  return os << "<" << v.first << ", " << v.second << ">";
}
const int INF = 1 << 30;
const ll INFL = 1LL << 60;
template <class T, class UpdateFunc, T update_unit>
class SegmentTree {
 public:
  int n;
  vector<T> data;
  UpdateFunc uf;
  SegmentTree(int nn) : n(1) {
    while (n < nn) n *= 2;
    data.resize(2 * n - 1, update_unit);
    for (int i = 0; i < (int)(data.size()); i++) data[i] = update_unit;
  }
  SegmentTree(vector<T> init) : n(1) {
    int nn = init.size();
    while (n < nn) n *= 2;
    data.resize(2 * n - 1, update_unit);
    copy(begin(init), end(init), begin(data) + n - 1);
  }
  T query(int i) {
    assert(0 <= i and i < n);
    return query(i, 0, 0, n);
  }
  void update(int a, int b, T v) {
    if (a == b) return;
    assert(0 <= a and a < b and b <= n);
    update(a, b, 0, 0, n, v);
  }

 private:
  void update(int a, int b, int i, int l, int r, T v) {
    if (out_of_range(a, b, l, r)) return;
    if (within_range(a, b, l, r))
      data[i] = uf(data[i], v);
    else {
      int m = (l + r) / 2;
      if (l < a) {
        update(l, a, left_child(i), l, m, data[i]);
        update(l, a, right_child(i), m, r, data[i]);
      }
      if (b < r) {
        update(b, r, left_child(i), l, m, data[i]);
        update(b, r, right_child(i), m, r, data[i]);
      }
      update(a, b, left_child(i), l, m, uf(data[i], v));
      update(a, b, right_child(i), m, r, uf(data[i], v));
      data[i] = update_unit;
    }
  }
  T query(int a, int i, int l, int r) {
    if (data.size() <= i) return update_unit;
    assert(l <= a and a < r);
    int m = (l + r) / 2;
    T v =
        a < m ? query(a, left_child(i), l, m) : query(a, right_child(i), m, r);
    return uf(v, data[i]);
  }
  static bool out_of_range(int a, int b, int l, int r) {
    return r <= a or b <= l;
  }
  static bool within_range(int a, int b, int l, int r) {
    return a <= l and r <= b;
  }
  static int left_child(int i) { return i * 2 + 1; }
  static int right_child(int i) { return i * 2 + 2; }
  static int parent(int i) { return (i - 1) / 2; }
};
template <class T>
struct Min {
  T operator()(const T &x, const T &y) const { return min(x, y); }
};
template <class T, T INIT>
using RangeMinQuery = SegmentTree<T, Min<T>, INIT>;
class Solver {
 public:
  bool solve() {
    int N, M;
    cin >> N >> M;
    vector<tuple<int, int, ll>> LRC(M);
    for (int i = 0; i < (int)(M); i++)
      cin >> get<0>(LRC[i]) >> get<1>(LRC[i]) >> get<2>(LRC[i]);
    for (int i = 0; i < (int)(M); i++) {
      get<0>(LRC[i])--;
    }
    sort(LRC.begin(), LRC.end());
    RangeMinQuery<ll, INFL> rmq(N + 1);
    rmq.update(0, 1, 0);
    int ptr = 0;
    for (int i = 0; i < (int)(N); i++) {
      ll val = -1;
      while (ptr < M and get<0>(LRC[ptr]) == i) {
        if (val < 0) val = rmq.query(i);
        rmq.update(get<0>(LRC[ptr]), get<1>(LRC[ptr]), val + get<2>(LRC[ptr]));
        ptr++;
      }
    }
    ll ans = rmq.query(N - 1);
    cout << (ans < INFL ? ans : -1) << endl;
    return 0;
  }
};
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  Solver s;
  s.solve();
  return 0;
}
