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: Runtime Error)

#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef int ll;
typedef long double ld;
const ll N = 100005;
char en = '\n';
ll inf = 1e17;
ll mod = 998244353;
ll power(ll x, ll n, ll mod) {
  ll res = 1;
  x %= mod;
  while (n) {
    if (n & 1)
      res = (res * x) % mod;
    x = (x * x) % mod;
    n >>= 1;
  }
  return res;
}

//
// Created by cs160 on 09-04-2019.
//
// ashishgup git

struct data {
  // Use required attributes
  int mn;

  // Default Values
  data() : mn(inf){};
};

struct SegTree {
  int N;
  vector<data> st;
  vector<bool> cLazy;
  vector<int> lazy;

  void init(int n) {
    N = n;
    st.resize(4 * N + 5);
    cLazy.assign(4 * N + 5, false);
    lazy.assign(4 * N + 5, inf);
  }

  // Write reqd merge functions
  void merge(data &cur, data &l, data &r) { cur.mn = min(l.mn, r.mn); }

  // Handle lazy propagation appriopriately
  void propagate(int node, int L, int R) {
    if (L != R) {
      cLazy[node * 2] = 1;
      cLazy[node * 2 + 1] = 1;
      lazy[node * 2] = min(lazy[node * 2], lazy[node]);
      lazy[node * 2 + 1] = min(lazy[node * 2 + 1], lazy[node]);
    }
    st[node].mn = min(st[node].mn, lazy[node]);
    cLazy[node] = 0;
  }

  void build(int node, int L, int R) {
    if (L == R) {
      st[node].mn = 1e9;
      return;
    }
    int M = (L + R) / 2;
    build(node * 2, L, M);
    build(node * 2 + 1, M + 1, R);
    merge(st[node], st[node * 2], st[node * 2 + 1]);
  }

  data Query(int node, int L, int R, int i, int j) {
    if (cLazy[node])
      propagate(node, L, R);
    if (j < L || i > R)
      return data();
    if (i <= L && R <= j)
      return st[node];
    int M = (L + R) / 2;
    data left = Query(node * 2, L, M, i, j);
    data right = Query(node * 2 + 1, M + 1, R, i, j);
    data cur;
    merge(cur, left, right);
    return cur;
  }

  data pQuery(int node, int L, int R, int pos) {
    if (cLazy[node])
      propagate(node, L, R);
    if (L == R)
      return st[node];
    int M = (L + R) / 2;
    if (pos <= M)
      return pQuery(node * 2, L, M, pos);
    else
      return pQuery(node * 2 + 1, M + 1, R, pos);
  }

  void Update(int node, int L, int R, int i, int j, int val) {
    if (cLazy[node])
      propagate(node, L, R);
    if (j < L || i > R)
      return;
    if (i <= L && R <= j) {
      cLazy[node] = 1;
      lazy[node] = min(lazy[node], val);
      propagate(node, L, R);
      return;
    }
    int M = (L + R) / 2;
    Update(node * 2, L, M, i, j, val);
    Update(node * 2 + 1, M + 1, R, i, j, val);
    merge(st[node], st[node * 2], st[node * 2 + 1]);
  }

  void pUpdate(int node, int L, int R, int pos, int val) {
    if (cLazy[node])
      propagate(node, L, R);
    if (L == R) {
      cLazy[node] = 1;
      lazy[node] = val;
      propagate(node, L, R);
      return;
    }
    int M = (L + R) / 2;
    if (pos <= M)
      pUpdate(node * 2, L, M, pos, val);
    else
      pUpdate(node * 2 + 1, M + 1, R, pos, val);
    merge(st[node], st[node * 2], st[node * 2 + 1]);
  }

  data query(int pos) { return pQuery(1, 1, N, pos); }

  data query(int l, int r) { return Query(1, 1, N, l, r); }

  void update(int pos, int val) { pUpdate(1, 1, N, pos, val); }

  void update(int l, int r, int val) { Update(1, 1, N, l, r, val); }
};

// Problem 1 (Max Query - Point Update with Coordinate Compression):
// http://codeforces.com/gym/100733/problem/F Solution 1:
// http://codeforces.com/gym/100733/submission/41643795

// Problem 2 (Min Query - Offline processing):
// https://codeforces.com/problemset/problem/522/D Solution 2:
// https://codeforces.com/contest/522/submission/45493164

struct node {
  ll L, R, c;
  node() {}
  node(ll L, ll R, ll c) : L(L), R(R), c(c) {}
};

bool comp(node &a, node &b) { return a.L < b.L; }
int32_t main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);

  ll n, m;
  cin >> n >> m;

  node arr[m + 5];

  for (ll i = 1; i <= m; i++) {
    cin >> arr[i].L >> arr[i].R >> arr[i].c;
  }

  sort(arr + 1, arr + m + 1, comp);

  ll curr = 1;

  ll ptr = 1;

  SegTree obj;
  obj.init(n);
  for (ll i = 1; i <= n; i++) {
    obj.update(i, i, inf);
  }
  obj.update(1, 1, 0);

  for (ll ptr = 1; ptr <= n; ptr++) {

    ll L = arr[ptr].L, R = arr[ptr].R, c = arr[ptr].c;
    ll min1 = obj.query(L, R).mn;

    obj.update(L, R, min1 + c);

    // curr = max(curr, R);
  }

  for (ll ptr = 1; ptr <= n; ptr++) {

    ll L = arr[ptr].L, R = arr[ptr].R, c = arr[ptr].c;
    ll min1 = obj.query(L, R).mn;

    obj.update(L, R, min1 + c);

    // curr = max(curr, R);
  }

  for (ll ptr = n; ptr >= 1; ptr--) {

    ll L = arr[ptr].L, R = arr[ptr].R, c = arr[ptr].c;
    ll min1 = obj.query(L, R).mn;

    obj.update(L, R, min1 + c);

    // curr = max(curr, R);
  }

  for (ll ptr = n; ptr >= 1; ptr--) {

    ll L = arr[ptr].L, R = arr[ptr].R, c = arr[ptr].c;
    ll min1 = obj.query(L, R).mn;

    obj.update(L, R, min1 + c);

    // curr = max(curr, R);
  }

  ll ans = obj.query(n, n).mn;
  if (ans > 1e15)
    cout << -1 << en;
  else
    cout << ans << en;

  return 0;
}