Problem:
Score : 600 points

Problem Statement

We have N points numbered 1 to N arranged in a line in this order.

Takahashi decides to make an undirected graph, using these points as the vertices.
In the beginning, the graph has no edge. Takahashi will do M operations to add edges in this graph.
The i-th operation is as follows:

The operation uses integers L_i and R_i between 1 and N (inclusive), and a positive integer C_i. For every pair of integers (s, t) such that L_i \leq s < t \leq R_i, add an edge of length C_i between Vertex s and Vertex t.

The integers L_1, ..., L_M, R_1, ..., R_M, C_1, ..., C_M are all given as input.

Takahashi wants to solve the shortest path problem in the final graph obtained. Find the length of the shortest path from Vertex 1 to Vertex N in the final graph.

Constraints

2 \leq N \leq 10^5

1 \leq M \leq 10^5

1 \leq L_i < R_i \leq N

1 \leq C_i \leq 10^9

Input

Input is given from Standard Input in the following format:

N M
L_1 R_1 C_1
:
L_M R_M C_M

Output

Print the length of the shortest path from Vertex 1 to Vertex N in the final graph.
If there is no shortest path, print -1 instead.

Sample Input 1

4 3
1 3 2
2 4 3
1 4 6

Sample Output 1

5

We have an edge of length 2 between Vertex 1 and Vertex 2, and an edge of length 3 between Vertex 2 and Vertex 4, so there is a path of length 5 between Vertex 1 and Vertex 4.

Sample Input 2

4 2
1 2 1
3 4 2

Sample Output 2

-1

Sample Input 3

10 7
1 5 18
3 4 8
1 3 5
4 7 10
5 9 8
6 10 5
8 10 3

Sample Output 3

28

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <stdio.h>
#include <iostream>
#include <cstdio>
#include <algorithm> 
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <map>
#include <list>
#include <utility>
#include <set>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <sstream>
#include <complex>
#include <stack>
#include <queue>
#include <numeric>
#include <bitset>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <random>

using namespace std;

static const double EPS = 1e-9;
template<class T> bool INRANGE(T x, T a, T b) { return a <= x && x <= b; }
template<class T> void amin(T &a, T v) { if (a > v) a = v; }
template<class T> void amax(T &a, T v) { if (a < v) a = v; }
int ROUND(double x) { return (int)(x + 0.5); }
bool ISINT(double x) { return fabs(ROUND(x) - x) <= EPS; }
bool ISEQUAL(double x, double y) { return fabs(x - y) <= EPS * max(1.0, max(fabs(x), fabs(y))); }
double SQSUM(double x, double y) { return x * x + y * y; }
#define PI  (acos(-1))
#define ARRAY_NUM(a) (sizeof(a)/sizeof(a[0])) 
#define NG (-1)
#define BIG ((int)1e9+10)
#define BIGLL ((ll)4e18)
#define SZ(a) ((int)(a).size())
#define SQ(a) ((a)*(a))
typedef unsigned long long ull;
typedef long long ll;

using namespace std;
typedef long long ll;

// modint: mod 計算を int を扱うように扱える構造体
template<int MOD>
struct ModInt {
	long long val;
	constexpr ModInt(long long v = 0) noexcept : val(v % MOD) {
		if (val < 0) v += MOD;
	}
	constexpr int getmod() { return MOD; }
	constexpr ModInt operator - () const noexcept {
		return val ? MOD - val : 0;
	}
	constexpr ModInt operator + (const ModInt& r) const noexcept { return ModInt(*this) += r; }
	constexpr ModInt operator - (const ModInt& r) const noexcept { return ModInt(*this) -= r; }
	constexpr ModInt operator * (const ModInt& r) const noexcept { return ModInt(*this) *= r; }
	constexpr ModInt operator / (const ModInt& r) const noexcept { return ModInt(*this) /= r; }
	constexpr ModInt& operator += (const ModInt& r) noexcept {
		val += r.val;
		if (val >= MOD) val -= MOD;
		return *this;
	}
	constexpr ModInt& operator -= (const ModInt& r) noexcept {
		val -= r.val;
		if (val < 0) val += MOD;
		return *this;
	}
	constexpr ModInt& operator *= (const ModInt& r) noexcept {
		val = val * r.val % MOD;
		return *this;
	}
	constexpr ModInt& operator /= (const ModInt& r) noexcept {
		long long a = r.val, b = MOD, u = 1, v = 0;
		while (b) {
			long long t = a / b;
			a -= t * b; swap(a, b);
			u -= t * v; swap(u, v);
		}
		val = val * u % MOD;
		if (val < 0) val += MOD;
		return *this;
	}
	constexpr bool operator == (const ModInt& r) const noexcept {
		return this->val == r.val;
	}
	constexpr bool operator != (const ModInt& r) const noexcept {
		return this->val != r.val;
	}

	friend ostream& operator << (ostream &os, const ModInt<MOD>& x) noexcept {
		return os << x.val;
	}
	friend istream& operator >> (istream &is, ModInt<MOD>& x) noexcept {
		return is >> x.val;
	}
	static constexpr ModInt<MOD> modpow(const ModInt<MOD> &a, long long n) noexcept {
		if (n == 0) return 1;
		auto t = modpow(a, n / 2);
		t = t * t;
		if (n & 1) t = t * a;
		return t;
	}
};

template<class T>
vector<T> make_vector(int n, T t) {
	return vector<T>(n, t);
}

template<class ...Ts>
auto make_vector(int n, Ts ... ts) {
	return vector<decltype(make_vector(ts...))>(n, make_vector(ts...));
}

#include<algorithm>
using ll = long long;

#define N 100003

class SegmentTree {
	const ll inf = 1e18;
	int n, n0;
	ll max_v[4 * N], smax_v[4 * N];
	ll sum[4 * N], max_c[4 * N];

	void update_node_max(int k, ll x) {
		sum[k] += (x - max_v[k]) * max_c[k];
		max_v[k] = x;
	}

	void push(int k) {
		if (max_v[k] < max_v[2 * k + 1]) {
			update_node_max(2 * k + 1, max_v[k]);
		}
		if (max_v[k] < max_v[2 * k + 2]) {
			update_node_max(2 * k + 2, max_v[k]);
		}
	}

	void update(int k) {
		sum[k] = sum[2 * k + 1] + sum[2 * k + 2];

		if (max_v[2 * k + 1] < max_v[2 * k + 2]) {
			max_v[k] = max_v[2 * k + 2];
			max_c[k] = max_c[2 * k + 2];
			smax_v[k] = max(max_v[2 * k + 1], smax_v[2 * k + 2]);
		}
		else if (max_v[2 * k + 1] > max_v[2 * k + 2]) {
			max_v[k] = max_v[2 * k + 1];
			max_c[k] = max_c[2 * k + 1];
			smax_v[k] = max(smax_v[2 * k + 1], max_v[2 * k + 2]);
		}
		else {
			max_v[k] = max_v[2 * k + 1];
			max_c[k] = max_c[2 * k + 1] + max_c[2 * k + 2];
			smax_v[k] = max(smax_v[2 * k + 1], smax_v[2 * k + 2]);
		}
	}

	void _update_min(ll x, int a, int b, int k, int l, int r) {
		if (b <= l || r <= a || max_v[k] <= x) {
			return;
		}
		if (a <= l && r <= b && smax_v[k] < x) {
			update_node_max(k, x);
			return;
		}

		push(k);
		_update_min(x, a, b, 2 * k + 1, l, (l + r) / 2);
		_update_min(x, a, b, 2 * k + 2, (l + r) / 2, r);
		update(k);
	}

	ll _query_max(int a, int b, int k, int l, int r) {
		if (b <= l || r <= a) {
			return 0;
		}
		if (a <= l && r <= b) {
			return max_v[k];
		}
		push(k);
		ll lv = _query_max(a, b, 2 * k + 1, l, (l + r) / 2);
		ll rv = _query_max(a, b, 2 * k + 2, (l + r) / 2, r);
		return max(lv, rv);
	}

	ll _query_sum(int a, int b, int k, int l, int r) {
		if (b <= l || r <= a) {
			return 0;
		}
		if (a <= l && r <= b) {
			return sum[k];
		}
		push(k);
		ll lv = _query_sum(a, b, 2 * k + 1, l, (l + r) / 2);
		ll rv = _query_sum(a, b, 2 * k + 2, (l + r) / 2, r);
		return lv + rv;
	}

public:
	SegmentTree(int n) {
		SegmentTree(n, nullptr);
	}

	SegmentTree(int n, ll *a) : n(n) {
		n0 = 1;
		while (n0 < n) n0 <<= 1;

		for (int i = 0; i<n; ++i) {
			max_v[n0 - 1 + i] = sum[n0 - 1 + i] = (a != nullptr ? a[i] : 0);
			smax_v[n0 - 1 + i] = -inf;
			max_c[n0 - 1 + i] = 1;
		}

		for (int i = n; i<n0; ++i) {
			max_v[n0 - 1 + i] = smax_v[n0 - 1 + i] = -inf;
			sum[n0 - 1 + i] = max_c[n0 - 1 + i] = 0;
		}
		for (int i = n0 - 2; i >= 0; i--) update(i);
	}

	// range minimize query
	void update_min(int a, int b, ll x) {
		return _update_min(x, a, b, 0, 0, n0);
	}

	// range maximum query
	ll query_max(int a, int b) {
		return _query_max(a, b, 0, 0, n0);
	}

	// range sum query
	ll query_sum(int a, int b) {
		return _query_sum(a, b, 0, 0, n0);
	}
};

int main()
{
	int n, m;
	cin >> n >> m;

	const ll BIGNOW = 1000000000 * 100005LL;

	ll a[100005];
	for (int i = 0; i < 100005; ++i)
	{
		a[i] = BIGNOW;
	}
	a[0] = 0;


	SegmentTree* seg = new SegmentTree(100005, a);


	vector < pair < pair <int, int> , ll > > vpr;


	for(int i=0;i<m;i++)
	{
		int l, r, c;	
		cin >> l >> r >> c;
		l--;
		r--;

		vpr.push_back(make_pair(make_pair(l, r), c) );
	}

	sort(vpr.begin(), vpr.end());

	for (int i = 0; i < SZ(vpr); ++i)
	{
		ll left = seg->query_max(vpr[i].first.first, vpr[i].first.first + 1);

		ll setCost = left + vpr[i].second;


		seg->update_min(vpr[i].first.first, vpr[i].first.second+1, setCost);
	}

	ll ret = seg->query_max(n-1, n);

	if (ret >= BIGNOW)
	{
		ret = NG;
	}

	cout << ret << endl;

	delete seg;

	return 0;
}