#include <iostream>
#include <string>
#include <sstream>
#include <iomanip> 
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <functional>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#include <bitset>

using namespace std;


// segment tree with lazy propagation class

#define MAX_ST_N 1000500	// # of total possible nodes = initial N + log N * Query number
#define INF (1LL << 61)

struct lst_node {
	long long val;				// range min
	long long offset;			// value added to this range
};

//lst_node node_list[MAX_ST_N * 4];

class lazy_segment_tree {
public:
	long long size;
	vector<lst_node> node_list;

	lazy_segment_tree() {
	}

	void initialize_empty(long long n) {		// initialize an empty segment tree
		size = n;
		lst_node lsd;
		lsd.val = 0;
		lsd.offset = 0;
		node_list.assign(size * 4 + 100, lsd);	// stored in 1-based, left = p * 2, right = p * 2 + 1s
	}

	long long build_tree(long long l, long long r, long long p, vector<long long>& a) {		// returns node list
		if (l == r) {
			node_list[p].val = a[l];
			node_list[p].offset = INF;

			return p;		// return node #
		}
		else {
			long long m = (l + r) >> 1;
			build_tree(l, m, p * 2, a);
			build_tree(m + 1, r, p * 2 + 1, a);

			// range min
			node_list[p].val = min(node_list[p * 2].val, node_list[p * 2 + 1].val);
			node_list[p].offset = INF;

			return p;
		}
	}

	void initialize(vector<long long>& a) {		// initialize with a vector
		size = a.size();
		node_list.assign(size * 4 + 100, { INF, 0 });

		build_tree(0, size - 1, 1, a);		// stored in 1-based, left = p * 2, right = p * 2 + 1s
	}

	long long update(long long pos, long long key) {		// create a new tree by cloning with #root_id and updating position p with new value key
															//long long ans = update_full(1, 0, size - 1, pos, key);
		long long ans = update_range_full(1, 0, size - 1, pos, pos, key);
		return ans;
	}

	//long long update_full(long long p, long long left, long long right, long long pos, long long key) {	// p = current node id
	//	if (left == right) {
	//		node_list[p].val = key;
	//		node_list[p].offset = 0;
	//		return p;		// return node #
	//	}
	//	else {
	//		long long m = (left + right) >> 1;
	//		long long a, b;
	//		if (pos <= m) {
	//			a = update_full(p * 2, left, m, pos, key);
	//			b = p * 2 + 1;
	//		}
	//		else {
	//			a = p * 2;
	//			b = update_full(p * 2 + 1, m + 1, right, pos, key);
	//		}

	//		// range min
	//		node_list[p].val = min(node_list[a].val, node_list[b].val);
	//		return p;
	//	}
	//}

	long long update_range(long long l, long long r, long long off) {
		long long ans = update_range_full(1, 0, size - 1, l, r, off);
		return ans;
	}

	long long update_range_full(long long p, long long left, long long right, long long l, long long r, long long off) { // p = current node id
		if ((left >= l) && (right <= r)) {
			// fully included in this range. set offset instead of change individual nodes

			if (left == right) {
				// leave node
				node_list[p].val = min(node_list[p].val, off);
				node_list[p].offset = 0;
			}
			else {
				node_list[p].offset = min(node_list[p].offset, off);
				node_list[p].val = min(min(node_list[p * 2].val, node_list[p * 2 + 1].val), node_list[p].offset);
			}
			return p;		// return node #
		}
		else {
			long long m = (left + right) >> 1;
			long long a, b;

			if (m >= l) a = update_range_full(p * 2, left, m, l, r, off);
			else a = p * 2;

			if (m + 1 <= r) b = update_range_full(p * 2 + 1, m + 1, right, l, r, off);
			else b = p * 2 + 1;

			// range min
			node_list[p].val = min(min(node_list[a].val, node_list[b].val), node_list[p].offset);
			// no need to change offset since the new off doesn't apply to the full range

			return p;
		}
	}

	long long query(long long l, long long r) {  // get range sum between l and r starting from the segment tree indicated by root_id
		if (l > r) {
			return INF;
		}
		return query_full(1, 0, size - 1, l, r, INF);
	}

	inline long long query_full(long long p, long long left, long long right, long long l, long long r, long long off) {	 // left/right = current range, l/r = intended query range; off = carried (uncommitted) offset from parents
		if ((left >= l) && (right <= r))
			return min(node_list[p].val, off);		// commit offset
		long long m = (left + right) >> 1, ans = INF;

		if (m >= l) {
			ans = min(ans, query_full(p * 2, left, m, l, r, min(off, node_list[p].offset)));
		}
		if (m + 1 <= r) {
			ans = min(ans, query_full(p * 2 + 1, m + 1, right, l, r, min(off, node_list[p].offset)));
		}
		return ans;
	}
};


int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);

	long long n, m, i, j, k, l, r, c, x;
	cin >> n >> m;
	vector<tuple<long long, long long, long long>> plist(m);
	for (i = 0; i < m; i++) {
		cin >> l >> r >> c;
		plist[i] = make_tuple(l, r, c);
	}
	sort(plist.begin(), plist.end());

	vector<long long> a(n + 2, INF);
	a[1] = 0;

	lazy_segment_tree lst;
	lst.initialize(a);
	for (auto p : plist) {
		tie(l, r, c) = p;
		x = lst.query(l, r);
		lst.update_range(l, r, x + c);

		//cout << "Processed " << l << " " << r << " " << c << "\n";
		//for (i = 1; i <= n; i++) {
		//	cout << lst.query(i, i) << " ";
		//}
		//cout << "\n\n";
	}

	x = lst.query(n, n); 
	if (x == INF) x = -1;
	cout << x << "\n";

	return 0;
}


Measured memory_bytes: 9472