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# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using SB = System.Text.StringBuilder;
//using System.Threading.Tasks;
//using System.Text.RegularExpressions;
//using System.Globalization;
//using System.Diagnostics;
using static System.Console;
using System.Numerics;
using static System.Math;
using pair = Pair<int, int>;

class Program
{
    static void Main()
    {
        //SetOut(new StreamWriter(OpenStandardOutput()) { AutoFlush = false });
        new Program().solve();
        Out.Flush();
    }
    readonly Scanner cin = new Scanner();
    readonly int[] dd = { 0, 1, 0, -1, 0 }; //→↓←↑
    readonly int mod = 1000000007;
    readonly int dom = 998244353;
    bool chmax<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) < 0) { a = b; return true; } return false; }
    bool chmin<T>(ref T a, T b) where T : IComparable<T> { if (b.CompareTo(a) < 0) { a = b; return true; } return false; }
    const long inf = long.MaxValue / 3;

    class Edge : IComparable<Edge>
    {
        public int from, to, id; public long cost;
        public Edge(int from, int to, long cost, int id = -1)
        {
            this.from = from;
            this.to = to;
            this.cost = cost;
            this.id = id;
        }
        public int CompareTo(Edge e) => from.CompareTo(e.from) != 0 ? from.CompareTo(e.from) : to.CompareTo(e.to);
        public override string ToString() => $"{from} {to} {cost}";
    }


    void solve()
    {
        int N = cin.nextint;
        int M = cin.nextint;
        var E = new Edge[M];
        for (int i = 0; i < M; i++)
        {
            E[i] = new Edge(cin.nextint - 1, cin.nextint - 1, cin.nextlong);
        }
        Array.Sort(E);
        //E.join("\n");

        var dp = new LazySegTree<long, long>(N, Min, (a, b, len) => Min(a, b), Min, inf);
        dp.Update(0, 0, 0);

        for (int i = 0; i < M; i++)
        {
            int s = E[i].from;
            int t = E[i].to;

            var before = dp[s, t];
            dp.Update(s, t, before + E[i].cost);
        }

        if (dp[N - 1, N - 1] == inf)
        {
            WriteLine(-1);
        }
        else
        {
            WriteLine(dp[N - 1, N - 1]);
        }
    }

}

/// <OriginalAuthor>riantkb</OriginalAuthor>
class LazySegTree<T, U>
{
    readonly int n;
    T[] data;
    U[] lazy;
    readonly bool[] is_lazy;
    readonly Func<T, T, T> calc;
    readonly Func<T, U, int, T> apply;
    readonly Func<U, U, U> merge;
    readonly T ex_data;

    /// <summary>
    /// 遅延セグメントツリーの構築
    /// </summary>
    /// <param name="m">要素数</param>
    /// <param name="calc">要素のマージ</param>
    /// <param name="apply">要素に作用素を作用</param>
    /// <param name="merge">作用素のマージ</param>
    /// <param name="ex_data">単位元</param>
    public LazySegTree(int m, Func<T, T, T> calc, Func<T, U, int, T> apply, Func<U, U, U> merge, T ex_data)
    {
        this.calc = calc;
        this.apply = apply;
        this.merge = merge;
        this.ex_data = ex_data;
        n = 1;
        while (n < m) n <<= 1;
        data = new T[n * 2 - 1];
        lazy = new U[n * 2 - 1];
        is_lazy = new bool[n * 2 - 1];
        for (int i = 0; i < data.Length; i++) data[i] = ex_data;
    }
    public LazySegTree(int m, Func<T, T, T> calc, Func<T, U, int, T> apply, Func<U, U, U> merge, T ex_data, T ini) : this(m, calc, apply, merge, ex_data)
    {
        for (int i = 0; i < m; i++) data[i + n - 1] = ini;
        for (int i = n - 2; i >= 0; i--) data[i] = calc(data[i * 2 + 1], data[i * 2 + 2]);
    }
    public LazySegTree(int m, Func<T, T, T> calc, Func<T, U, int, T> apply, Func<U, U, U> merge, T ex_data, IList<T> ini) : this(m, calc, apply, merge, ex_data)
    {
        for (int i = 0; i < m; i++) data[i + n - 1] = ini[i];
        for (int i = n - 2; i >= 0; i--) data[i] = calc(data[i * 2 + 1], data[i * 2 + 2]);
    }
    void assign_lazy(int k, U x)
    {
        if (k >= lazy.Length) return;
        if (is_lazy[k]) lazy[k] = merge(lazy[k], x);
        else
        {
            is_lazy[k] = true;
            lazy[k] = x;
        }
    }
    void eval(int k, int len)
    {
        if (!is_lazy[k]) return;
        assign_lazy(k * 2 + 1, lazy[k]);
        assign_lazy(k * 2 + 2, lazy[k]);
        data[k] = apply(data[k], lazy[k], len);
        is_lazy[k] = false;
    }
    T update(int s, int t, U x, int k, int l, int r)
    {
        eval(k, r - l);
        if (r <= s || t <= l) return data[k];
        if (s <= l && r <= t)
        {
            assign_lazy(k, x);
            return apply(data[k], lazy[k], r - l);
        }
        return data[k] = calc(update(s, t, x, k * 2 + 1, l, (l + r) / 2),
                              update(s, t, x, k * 2 + 2, (l + r) / 2, r));
    }
    T run(int s, int t, int k, int l, int r)
    {
        eval(k, r - l);
        if (r <= s || t <= l) return ex_data;
        if (s <= l && r <= t) return data[k];
        return calc(run(s, t, k * 2 + 1, l, (l + r) / 2),
                    run(s, t, k * 2 + 2, (l + r) / 2, r));
    }

    /// <summary>update [s, t]</summary>
    public void Update(int s, int t, U x) { t++; update(s, t, x, 0, 0, n); }
    /// <summary>return node[s, t]</summary>
    public T this[int s, int t] => Run(s, t);
    T Run(int s, int t) { t++; return run(s, t, 0, 0, n); }

    public T[] Items
    {
        get
        {
            var ret = new T[n];
            for (int i = 0; i < ret.Length; i++)
            {
                ret[i] = Run(i, i);
            }
            return ret;
        }
    }
}

static class Ex
{
    public static void join<T>(this IEnumerable<T> values, string sep = " ") => WriteLine(string.Join(sep, values));
    public static string concat<T>(this IEnumerable<T> values) => string.Concat(values);
    public static string reverse(this string s) { var t = s.ToCharArray(); Array.Reverse(t); return t.concat(); }

    public static int lower_bound<T>(this IList<T> arr, T val) where T : IComparable<T>
    {
        int low = 0, high = arr.Count;
        int mid;
        while (low < high)
        {
            mid = ((high - low) >> 1) + low;
            if (arr[mid].CompareTo(val) < 0) low = mid + 1;
            else high = mid;
        }
        return low;
    }
    public static int upper_bound<T>(this IList<T> arr, T val) where T : IComparable<T>
    {
        int low = 0, high = arr.Count;
        int mid;
        while (low < high)
        {
            mid = ((high - low) >> 1) + low;
            if (arr[mid].CompareTo(val) <= 0) low = mid + 1;
            else high = mid;
        }
        return low;
    }
}

class Pair<T, U> : IComparable<Pair<T, U>> where T : IComparable<T> where U : IComparable<U>
{
    public T f; public U s;
    public Pair(T f, U s) { this.f = f; this.s = s; }
    public int CompareTo(Pair<T, U> a) => f.CompareTo(a.f) != 0 ? f.CompareTo(a.f) : s.CompareTo(a.s);
    public override string ToString() => $"{f} {s}";
}

class Scanner
{
    string[] s; int i;
    readonly char[] cs = new char[] { ' ' };
    public Scanner() { s = new string[0]; i = 0; }
    public string[] scan => ReadLine().Split();
    public int[] scanint => Array.ConvertAll(scan, int.Parse);
    public long[] scanlong => Array.ConvertAll(scan, long.Parse);
    public double[] scandouble => Array.ConvertAll(scan, double.Parse);
    public string next
    {
        get
        {
            if (i < s.Length) return s[i++];
            string st = ReadLine();
            while (st == "") st = ReadLine();
            s = st.Split(cs, StringSplitOptions.RemoveEmptyEntries);
            i = 0;
            return next;
        }
    }
    public int nextint => int.Parse(next);
    public long nextlong => long.Parse(next);
    public double nextdouble => double.Parse(next);
}