#define _CRT_SECURE_NO_WARNINGS

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <cstring>
#include <map>
#include <utility>
#include <set>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <list>
#include <algorithm>
#include <functional>
#include <sstream>
#include <complex>
#include <stack>
#include <queue>
#include <unordered_set>
#include <unordered_map>
#include <array>
#include <cassert>
#include <bitset>
#include <cstdint>
using namespace std;
using LL = long long;

//区間上のすべての要素を変更する処理ができるセグ木
template<typename T, typename Comp>
class RMQ_modify {
private:
	const T DEF;//デフォルト値
	vector<T> seg;//生データ
	int width;//セグ木の幅(配列の大きさではない！)
	vector<T>lazy;//遅延データ
	vector<bool>flag;//遅延データの有無
	//k番目のノード[l,r)の遅延伝播をする
	void eval(int k, int l, int r) {
		if (flag[k]) {
			seg[k] = lazy[k];
			if (r - l > 1) {
				lazy[2 * k + 1] = lazy[k]; flag[2 * k + 1] = true;
				lazy[2 * k + 2] = lazy[k]; flag[2 * k + 2] = true;
			}
			lazy[k] = T(); flag[k] = false;
		}
	}
	T query_raw(int a, int b, int l, int r, int k) {
		eval(k, l, r);
		if (b <= l || r <= a)return DEF;
		if (a <= l && r <= b)return seg[k];
		T vl = query_raw(a, b, l, (l + r) / 2, 2 * k + 1);
		T vr = query_raw(a, b, (l + r) / 2, r, 2 * k + 2);
		return min(vl, vr, Comp());
	}
	void update_raw(int a, int b, T x, int l, int r, int k) {
		eval(k, l, r);
		if (b <= l || r <= a)return;
		if (a <= l && r <= b) {
			lazy[k] = x; flag[k] = true;
			eval(k, l, r);
		}
		else {
			update_raw(a, b, x, l, (l + r) / 2, 2 * k + 1);
			update_raw(a, b, x, (l + r) / 2, r, 2 * k + 2);
			seg[k] = min(seg[2 * k + 1], seg[2 * k + 2], Comp());
		}
	}
public:
	//サイズn、デフォルト値defのセグ木を作る
	RMQ_modify(int n, T def) :DEF(def) {
		width = 1;
		while (width < n)width *= 2;
		seg.assign(width * 2 - 1, DEF);
		lazy.assign(seg.size(), T());
		flag.assign(seg.size(), false);
	}
	//区間[a,b)の答えを取得する
	T query(int a, int b) { return query_raw(a, b, 0, width, 0); }
	//区間[a,b)に一様に値xを加算する
	void update(int a, int b, T x) { update_raw(a, b, x, 0, width, 0); }
	//配列ごと初期化する
	void init(const vector<T>& vec) {
		for (int i = 0; i < min(width, (int)vec.size()); i++)
			seg[i + width - 1] = vec[i];
		for (int i = width - 2; i >= 0; i--)
			seg[i] = min(seg[i * 2 + 1], seg[i * 2 + 2], Comp());
		fill(lazy.begin(), lazy.end(), T());
		fill(flag.begin(), flag.end(), false);
	}
};

using TREE = RMQ_modify<LL, less<LL>>;

int N, M;
const LL INF = 12345678901234567LL;

int main() {
	cin >> N >> M;
	vector<pair<pair<int, int>, LL>>vec;
	for (int i = 0; i < M; ++i) {
		int L, R;
		LL C;
		cin >> L >> R;
		cin >> C;
		--L;
		vec.push_back({ {L,R},C });
	}
	sort(vec.begin(), vec.end());
	TREE tree(N, INF);
	tree.update(0, 1, 0);
	for (auto& elm : vec) {
		int L = elm.first.first;
		int R = elm.first.second;
		LL C = elm.second;
		LL value = tree.query(L, L + 1) + C;
		int lo = L, hi = R;
		while (hi - lo > 1) {
			int mid = (lo + hi) / 2;
			auto youso = tree.query(mid, mid + 1);
			if (youso > value) {
				hi = mid;
			}
			else {
				lo = mid;
			}
		}
		if (hi == R)continue;
		tree.update(hi, R, value);
	}
	LL ans = tree.query(N - 1, N);
	if (ans == INF) {
		cout << -1 << endl;
	}
	else {
		cout << ans << endl;
	}
	return 0;
}

Measured memory_bytes: 7920