#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>

#define debug(...) fprintf(stderr, __VA_ARGS__)

#ifndef AT_HOME
#define getchar() IO::myGetchar()
#define putchar(x) IO::myPutchar(x)
#endif

namespace IO {
	static const int IN_BUF = 1 << 23, OUT_BUF = 1 << 23;

	inline char myGetchar() {
		static char buf[IN_BUF], *ps = buf, *pt = buf;
		if (ps == pt) {
			ps = buf, pt = buf + fread(buf, 1, IN_BUF, stdin);
		}
		return ps == pt ? EOF : *ps++;
	}

	template<typename T>
	inline bool read(T &x) {
		bool op = 0;
		char ch = getchar();
		x = 0;
		for (; !isdigit(ch) && ch != EOF; ch = getchar()) {
			op ^= (ch == '-');
		}
		if (ch == EOF) {
			return false;
		}
		for (; isdigit(ch); ch = getchar()) {
			x = x * 10 + (ch ^ '0');
		}
		if (op) {
			x = -x;
		}
		return true;
	}

	inline int readStr(char *s) {
		int n = 0;
		char ch = getchar();
		for (; isspace(ch) && ch != EOF; ch = getchar())
			;
		for (; !isspace(ch) && ch != EOF; ch = getchar()) {
			s[n++] = ch;
		}
		s[n] = '\0';
		return n;
	}

	inline void myPutchar(char x) {
		static char pbuf[OUT_BUF], *pp = pbuf;
		struct _flusher {
			~_flusher() {
				fwrite(pbuf, 1, pp - pbuf, stdout);
			}
		};
		static _flusher outputFlusher;
		if (pp == pbuf + OUT_BUF) {
			fwrite(pbuf, 1, OUT_BUF, stdout);
			pp = pbuf;
		}
		*pp++ = x;
	}

	template<typename T>
	inline void print_(T x) {
		if (x == 0) {
			putchar('0');
			return;
		}
		std::vector<int> num;
		if (x < 0) {
			putchar('-');
			x = -x;
		}
		for (; x; x /= 10) {
			num.push_back(x % 10);
		}
		while (!num.empty()) {
			putchar(num.back() ^ '0');
			num.pop_back();
		}
	}

	template<typename T>
	inline void print(T x, char ch = '\n') {
		print_(x);
		putchar(ch);
	}

	inline void printStr_(const char *s, int n = -1) {
		if (n == -1) {
			n = strlen(s);
		}
		for (int i = 0; i < n; ++i) {
			putchar(s[i]);
		}
	}

	inline void printStr(const char *s, int n = -1, char ch = '\n') {
		printStr_(s, n);
		putchar(ch);
	}
}
using namespace IO;

const int N = 100005;

int n, m, id[N];

struct Graph {
	static const int N = 500005;
	static const long long INF = 0x3f3f3f3f3f3f3f3fll;

	std::vector<std::pair<int, int>> E[N];
	bool vis[N];
	long long dis[N];

	void addEdge(int u, int v, int w) {
		E[u].push_back({v, w});
	}

	long long Dijkstra(int n, int s, int t) {
		for (int i = 1; i <= n; ++i) {
			vis[i] = 0;
			dis[i] = INF;
		}
		std::priority_queue<std::pair<long long, int>> Q;
		dis[s] = 0, Q.push({0, s});
		while (!Q.empty()) {
			int u = Q.top().second;
			Q.pop();
			if (vis[u]) {
				continue;
			}
			vis[u] = 1;
			for (auto p : E[u]) {
				int v = p.first, w = p.second;
				if (dis[v] > dis[u] + w) {
					dis[v] = dis[u] + w;
					Q.push({-dis[v], v});
				}
			}
		}
		return dis[t];
	}
} G;

struct SegmentTree {
	int rt, cnt;
	int ls[N << 1], rs[N << 1];

	void build(int &u, int l, int r) {
		u = ++cnt, ls[u] = rs[u] = 0;
		if (l == r) {
			id[l] = u;
			return;
		}
		int md = (l + r) >> 1;
		build(ls[u], l, md), build(rs[u], md + 1, r);
		G.addEdge(ls[u], u, 0), G.addEdge(rs[u], u, 0);
	}

	void link(int u, int l, int r, int L, int R, int t, int w) {
		if (L <= l && r <= R) {
			G.addEdge(u, t, w);
			G.addEdge(t, u + cnt, w);
			return;
		}
		int md = (l + r) >> 1;
		if (L <= md) {
			link(ls[u], l, md, L, R, t, w);
		}
		if (R > md) {
			link(rs[u], md + 1, r, L, R, t, w);
		}
	}
} T;

int main() {
	read(n), read(m);
	T.build(T.rt, 1, n);
	int cnt = T.cnt;
	for (int i = 1; i <= cnt; ++i) {
		if (T.ls[i] && T.rs[i]) {
			G.addEdge(i + cnt, T.ls[i] + cnt, 0);
			G.addEdge(i + cnt, T.rs[i] + cnt, 0);
		}
	}
	for (int i = 1; i <= n; ++i) {
		G.addEdge(id[i] + cnt, id[i], 0);
	}
	cnt *= 2;
	for (int i = 1; i <= m; ++i) {
		int l, r, w;
		read(l), read(r), read(w);
		++cnt;
		T.link(T.rt, 1, n, l, r, cnt, w);
	}
	long long ans = G.Dijkstra(cnt, id[1], id[n] + T.cnt);
	if (ans == G.INF) {
		print(-1);
	} else {
		print(ans / 2);
	}
}


Measured memory_bytes: 67880