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 "bits/stdc++.h"
using namespace std;

const long long inf = 1LL << 60;


// Index range: [0, n)
// Supported Operations are:
// * Range Update with operator E: T -> T and an associative operation h(E, E) -> E
// * Aggregation over associative operation f(T, T) -> T
// Constraints
// * for c in e, c(f(a, b)) = f(c(a), c(b)). operators in E and aggregation f are swappable.
// * for b, c in e, c(b(a)) = h(b, c)(a). g is a merger for operator E.

template <class T, class E>
struct RangeUpdateSegmentTree {
    T aggregation(T x, T y) {
        // y is right element
        return min(x, y);
    }

    T apply(E e, T t) {
        return min(e, t);
    }

    E merge(E x, E y) {
        // y is applied later
        return min(x, y);
    }

    T default_element() {
        // identity of aggregation
        return inf;
    }

    E default_operator() {
        // identity of merge
        return inf;
    }

    int offset;
    vector<T> buffer;
    vector<E> operator_buffer;

    RangeUpdateSegmentTree(const vector<T>& initial_values) {
        const int n = initial_values.size();
        int row_length = 1;
        while (n > row_length) {
            row_length *= 2;
        }
        offset = row_length - 1;
        buffer = vector<T>(row_length * 2, default_element());
        operator_buffer = vector<E>(row_length * 2, default_operator());
        for (int i = 0; i < n; ++i) {
            buffer[offset + i] = initial_values[i];
        }
        initialize_buffer();
    }

    void initialize_buffer() {
        for (int i = offset - 1; i >= 0; --i) {
            buffer[i] = aggregation(buffer[2 * i + 1], buffer[2 * i + 2]);
        }
    }

    void propagate(int i) {
        if (operator_buffer[i] == default_operator()) {
            return;
        }
        if (i * 2 + 2 < operator_buffer.size()) {
            operator_buffer[i * 2 + 1] = merge(operator_buffer[i * 2 + 1], operator_buffer[i]);
            operator_buffer[i * 2 + 2] = merge(operator_buffer[i * 2 + 2], operator_buffer[i]);
        }
        buffer[i] = apply(operator_buffer[i], buffer[i]);
        operator_buffer[i] = default_operator();
    }

    // [l, r)
    T aggregate(int l, int r) {
        return aggregate_recursive(l, r, 0, 0, offset + 1);
    }

    T aggregate_recursive(int l, int r, int i, int p, int q) {
        propagate(i);
        if (q <= l || r <= p) {
            return default_element();
        }
        if (l <= p && q <= r) {
            return buffer[i];
        }
        const int left = 2 * i + 1;
        const int right = left + 1;
        const int m = (p + q) / 2;

        return aggregation(aggregate_recursive(l, r, left, p, m), aggregate_recursive(l, r, right, m, q));
    }

    // for i in [l, r), buf[i] := E(buf[i])
    void update(int l, int r, E x) {
        update_recursive(l, r, x, 0, 0, offset + 1);
    }

    T update_recursive(int l, int r, E x, int i, int p, int q) {
        propagate(i);
        if (q <= l || r <= p) {
            return buffer[i];
        }
        if (l <= p && q <= r) {
            operator_buffer[i] = merge(operator_buffer[i], x);
            return apply(operator_buffer[i], buffer[i]);
        }
        const int left = 2 * i + 1;
        const int right = left + 1;
        const int m = (p + q) / 2;

        return buffer[i] = aggregation(update_recursive(l, r, x, left, p, m), update_recursive(l, r, x, right, m, q));
    }

    T get_at(int i) {
        return aggregate(i, i + 1);
    }
};

// verify: https://atcoder.jp/contests/nikkei2019-2-qual/tasks/nikkei2019_2_qual_d

typedef long long li;

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

    vector<li> ls(m), rs(m), cs(m);
    vector<pair<li, li>> lis;
    for (int i = 0; i < m; ++i) {
        cin >> ls[i] >> rs[i] >> cs[i];
        ls[i]--;
        rs[i]--;
        lis.emplace_back(ls[i], i);
    }
    sort(lis.begin(), lis.end());

    vector<li> cost(n + 1, inf);
    cost[0] = 0;
    RangeUpdateSegmentTree<li, li> tree(cost);

    for (int i = 0; i < m; ++i) {
        int idx = lis[i].second;
        li md = tree.aggregate(ls[idx], rs[idx] + 1);
        tree.update(ls[idx], rs[idx] + 1, md + cs[idx]);
    }

    li ans = tree.get_at(n - 1);
    if (ans == inf) {
        ans = -1;
    }
    cout << ans << endl;
    return 0;
}