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 Rust (1.42.0) (judge verdict: Accepted)

// ---------- decrease key test ----------
#[derive(Clone, Copy, PartialEq, Eq)]
struct Pointer(usize);
 
impl Pointer {
    const NULL: usize = std::usize::MAX;
    fn new(p: usize) -> Self {
        Pointer(p)
    }
    fn set(&mut self, x: usize) {
        self.0 = x;
    }
    fn get(&self) -> Option<usize> {
        if self.is_null() {
            None
        } else {
            Some(self.0)
        }
    }
    fn clear(&mut self) {
        self.set(Self::NULL);
    }
    fn is_null(&self) -> bool {
        self.0 == Self::NULL
    }
}
 
impl Default for Pointer {
    fn default() -> Self {
        Pointer::new(Pointer::NULL)
    }
}
 
struct Node<K, V> {
    key: K,
    value: V,
    parent: Pointer,
    child: Pointer,
    left: Pointer,
    right: Pointer,
}
 
impl<K, V> Node<K, V> {
    fn new(key: K, value: V) -> Self {
        Node {
            key: key,
            value: value,
            parent: Pointer::default(),
            child: Pointer::default(),
            left: Pointer::default(),
            right: Pointer::default(),
        }
    }
    fn rooting(&mut self, x: usize) {
        self.parent.clear();
        self.left.set(x);
        self.right.set(x);
    }
}
 
struct Heap<K, V> {
    array: Vec<Node<K, V>>,
    free: Pointer,
    root: Pointer,
}
 
impl<K: Ord + Copy, V: Copy> Heap<K, V> {
    fn new() -> Self {
        Heap {
            array: vec![],
            free: Pointer::default(),
            root: Pointer::default(),
        }
    }
    fn meld(&mut self, x: Pointer, y: Pointer) -> Pointer {
        if x.is_null() {
            return y;
        }
        if y.is_null() {
            return x;
        }
        let mut x = x.get().unwrap();
        let mut y = y.get().unwrap();
        let node = &mut self.array;
        if node[x].key >= node[y].key {
            std::mem::swap(&mut x, &mut y);
        }
        node[y].parent.set(x);
        let child = node[x].child;
        node[x].child.set(y);
        if let Some(c) = child.get() {
            let r = node[c].right.get().unwrap();
            node[c].right.set(y);
            node[r].left.set(y);
            node[y].left.set(c);
            node[y].right.set(r);
        }
        Pointer::new(x)
    }
    fn merge_list(&mut self, lst: Pointer) -> Pointer {
        if lst.is_null() {
            return lst;
        }
        let k = lst.get().unwrap();
        let l = self.array[k].left.get().unwrap();
        self.array[l].right.clear();
        self.array[k].left.clear();
        let mut lst = lst;
        let mut root = Pointer::default();
        while let Some(a) = lst.get() {
            if let Some(b) = self.array[a].right.get() {
                lst = self.array[b].right;
                self.array[a].rooting(a);
                self.array[b].rooting(b);
                let x = self.meld(Pointer::new(a), Pointer::new(b));
                root = self.meld(root, x);
            } else {
                lst.clear();
                self.array[a].rooting(a);
                root = self.meld(root, Pointer::new(a));
            }
        }
        root
    }
    fn push(&mut self, key: K, value: V) -> Pointer {
        if self.free.is_null() {
            let x = self.array.len();
            self.free.set(x);
            self.array.push(Node::new(key, value));
        }
        let res = self.free;
        let x = res.get().unwrap();
        self.free = self.array[x].child;
        self.array[x] = Node::new(key, value);
        self.array[x].rooting(x);
        self.root = self.meld(self.root, res);
        res
    }
    fn pop(&mut self) -> Option<(K, V)> {
        let root = self.root;
        root.get().map(|root| {
            let lst = self.array[root].child;
            self.array[root].child = self.free;
            self.free.set(root);
            self.root = self.merge_list(lst);
            (self.array[root].key, self.array[root].value)
        })
    }
    fn decrease_key(&mut self, p: Pointer, key: K) {
        let p = p.get().unwrap();
        assert!(key < self.array[p].key);
        self.array[p].key = key;
        let parent = self.array[p].parent;
        if parent.get().map_or(false, |q| self.array[q].key > key) {
            let q = parent.get().unwrap();
            let l = self.array[p].left.get().unwrap();
            let r = self.array[p].right.get().unwrap();
            self.array[l].right.set(r);
            self.array[r].left.set(l);
            self.array[p].rooting(p);
            if self.array[q].child.get().unwrap() == p {
                self.array[q].child.set(r);
            }
            if self.array[q].child.get().unwrap() == p {
                self.array[q].child.clear();
            }
            self.root = self.meld(self.root, Pointer::new(p));
        }
    }
}
// ---------- decrease key test ----------
// ---------- begin chmin, chmax ----------
trait ChangeMinMax {
    fn chmin(&mut self, x: Self) -> bool;
    fn chmax(&mut self, x: Self) -> bool;
}

impl<T: PartialOrd> ChangeMinMax for T {
    fn chmin(&mut self, x: Self) -> bool {
        *self > x && {
            *self = x;
            true
        }
    }
    fn chmax(&mut self, x: Self) -> bool {
        *self < x && {
            *self = x;
            true
        }
    }
}
// ---------- end chmin, chmax ----------
// ---------- begin segment tree closure ----------
struct SegmentTree<T> {
    size: usize,
    val: Vec<Option<T>>,
}

#[allow(dead_code)]
impl<T> SegmentTree<T> 
where
    T: Clone
{
    fn new(size: usize) -> Self {
        let size = size.next_power_of_two();
        SegmentTree {
            size: size,
            val: (0..(2 * size)).map(|_| None).collect(),
        }
    }
    fn build_by<F>(a: &[T], mut f: F) -> Self
    where
        F: FnMut(&T, &T) -> T,
    {
        let size = a.len().next_power_of_two();
        let mut val = (0..(2 * size)).map(|_| None).collect::<Vec<_>>();
        for (v, a) in val[size..].iter_mut().zip(a.iter()) {
            *v = Some(a.clone());
        }
        for x in (1..size).rev() {
            val[x] = match (val[2 * x].as_ref(), val[2 * x + 1].as_ref()) {
                (Some(l), Some(r)) => Some(f(l, r)),
                _ => val[2 * x].clone().or_else(|| val[2 * x + 1].clone()),
            };
        }
        SegmentTree {
            size: size,
            val: val,
        }
    }
    fn update<F>(&mut self, x: usize, val: Option<T>, mut f: F)
    where
        F: FnMut(&T, &T) -> T,
    {
        assert!(x < self.size);
        let mut x = x + self.size;
        self.val[x] = val;
        let val = &mut self.val;
        x >>= 1;
        while x > 0 {
            val[x] = match (val[2 * x].as_ref(), val[2 * x + 1].as_ref()) {
                (Some(l), Some(r)) => Some(f(l, r)),
                _ => val[2 * x].clone().or_else(|| val[2 * x + 1].clone()),
            };
            x >>= 1;
        }
    }
    fn query<F>(&self, l: usize, r: usize, mut f: F)
    where
        F: FnMut(&T),
    {
        assert!(l <= r && r <= self.size);
        let mut l = self.size + l;
        let mut r = self.size + r;
        let val = &self.val;
        while l < r {
            if l & 1 == 1 {
                val[l].as_ref().map(|p| f(p));
                l += 1;
            }
            if r & 1 == 1 {
                r -= 1;
                val[r].as_ref().map(|p| f(p));
            }
            l >>= 1;
            r >>= 1;
        }
    }
}
// ---------- end segment tree closure ----------

use proconio::*;
use proconio::marker::*;
use std::cmp::*;

fn run() {
    input! {
        n: usize,
        m: usize,
        e: [(Usize1, usize, u64); m],
    }
    let ini = (0..n).collect::<Vec<_>>();
    let mut id = n;
    let mut gen = || {
        let v = id;
        id += 1;
        v
    };
    let mut edge = vec![];
    let up = SegmentTree::build_by(&ini, |a, b| {
        let v = gen();
        edge.push((*a, v, 0));
        edge.push((*b, v, 0));
        v
    });
    let down = SegmentTree::build_by(&ini, |a, b| {
        let v = gen();
        edge.push((v, *a, 0));
        edge.push((v, *b, 0));
        v
    });
    for (l, r, c) in e {
        let src = gen();
        let dst = gen();
        edge.push((src, dst, c));
        up.query(l, r, |v| {
            edge.push((*v, src, 0));
        });
        down.query(l, r, |v| {
            edge.push((dst, *v, 0));
        });
    }
    let size = gen();
    let mut cnt = vec![0; size];
    for &(s, _, _) in edge.iter() {
        cnt[s] += 1;
    }
    let mut g = cnt.into_iter().map(|c| Vec::with_capacity(c)).collect::<Vec<_>>();
    for (s, t, c) in edge {
        g[s].push((t, c));
    }
    let mut dp = vec![std::u64::MAX; size];
    let mut po = vec![Pointer::default(); size];
    dp[0] = 0;
    let mut h = Heap::new();
    h.push(0, 0);
    while let Some((d, v)) = h.pop() {
        if d > dp[v] {
            continue;
        }
        for &(u, c) in g[v].iter() {
            let d = d + c;
            if dp[u].chmin(d) {
                if po[u].is_null() {
                    po[u] = h.push(d, u);
                } else {
                    h.decrease_key(po[u], d);
                }
            }
        }
    }
    let ans = dp[n - 1];
    if ans == std::u64::MAX {
        println!("-1");
    } else {
        println!("{}", ans);
    }
}

fn main() {
    run();
}