#[allow(unused_imports)]
use std::cmp::Ordering;

#[allow(unused_imports)]
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};

#[allow(unused_imports)]
use std::io::{stdin, stdout, BufWriter, Write};

#[allow(unused_imports)]
use std::iter::FromIterator;

#[allow(unused_macros)]
macro_rules! min {
    ($x: expr) => ($x);
    ($x: expr, $($z: expr),+) => {{
        std::cmp::min($x, min!($($z),*))
    }}
}

#[allow(unused_macros)]
macro_rules! max {
    ($x: expr) => ($x);
    ($x: expr, $($z: expr),+) => {{
        std::cmp::max($x, max!($($z),*))
    }}
}

#[allow(unused_macros)]
macro_rules! get {
    ([$t: ty]) => {
        {
            let mut line = String::new();
            stdin().read_line(&mut line).unwrap();
            line.split_whitespace().map(|t|t.parse::<$t>().unwrap()).collect::<Vec<_>>()
        }
    };
    ([$t: ty];$n: expr) => {
        (0..$n).map(|_|get!([$t])).collect::<Vec<_>>()
    };
    ($t: ty) => {
        {
            let mut line = String::new();
            stdin().read_line(&mut line).unwrap();
            line.trim().parse::<$t>().unwrap()
        }
    };
    ($($t: ty),*) => {
        {
            let mut line = String::new();
            stdin().read_line(&mut line).unwrap();
            let mut iter = line.split_whitespace();
            ($(iter.next().unwrap().parse::<$t>().unwrap(),)*)
        }
    };
    ($t: ty; $n: expr) => {
        (0..$n).map(|_|get!($t)).collect::<Vec<_>>()
    };
    ($($t: ty),*; $n: expr) => {
        (0..$n).map(|_|get!($($t),*)).collect::<Vec<_>>()
    };
}

#[allow(unused_macros)]
macro_rules! debug {
    ($($a:expr),*) => {
        #[cfg(debug_assertions)]
        writeln!(&mut std::io::stderr(), concat!("[DEBUG] ", $(stringify!($a), "={:?} "),*), $($a),*).unwrap();
    }
}

const BIG_STACK_SIZE: bool = true;

#[allow(dead_code)]
fn main() {
    use std::thread;
    if BIG_STACK_SIZE {
        thread::Builder::new()
            .stack_size(32 * 1024 * 1024)
            .name("solve".into())
            .spawn(solve)
            .unwrap()
            .join()
            .unwrap();
    } else {
        solve();
    }
}

pub trait Monoid<T>: SemiGroup<T> {
    fn identity() -> T;
}
pub trait SemiGroup<T>: Magma<T> {}
pub trait Magma<T> {
    fn operate(lhs: T, rhs: T) -> T;
}
use self::lazysegtree::{Effection, LazySegmentTree, MultiOperator};
mod lazysegtree {
    use super::Monoid;
    use std;
    use std::marker::PhantomData;
    pub trait Effection<T, E> {
        fn operate(element: T, effector: E) -> T;
    }
    pub trait MultiOperator<E> {
        fn multi_operate(element: E, num: usize) -> E;
    }
    #[derive(Debug)]
    pub struct LazySegmentTree<T, MT, E, ME, A, P> {
        n: usize,
        data: Vec<T>,
        lazy_data: Vec<E>,
        value_monoid: PhantomData<fn() -> MT>,
        effector_monoid: PhantomData<fn() -> ME>,
        effection: PhantomData<fn() -> A>,
        multi_operator: PhantomData<fn() -> P>,
    }
    impl<T, MT, E, ME, A, P> LazySegmentTree<T, MT, E, ME, A, P>
    where
        MT: Monoid<T>,
        T: Copy + Clone + std::fmt::Debug,
        ME: Monoid<E>,
        E: Copy + Clone + std::fmt::Debug + Eq,
        A: Effection<T, E>,
        P: MultiOperator<E>,
    {
        pub fn new(nt: usize) -> Self {
            let mut n = 1;
            while n < nt {
                n *= 2;
            }
            LazySegmentTree {
                n: n,
                data: vec![MT::identity(); 2 * n - 1],
                lazy_data: vec![ME::identity(); 2 * n - 1],
                value_monoid: PhantomData,
                effector_monoid: PhantomData,
                effection: PhantomData,
                multi_operator: PhantomData,
            }
        }
        fn evaluate(&mut self, len: usize, index: usize) {
            if self.lazy_data[index] == ME::identity() {
                return;
            }
            if 2 * index + 1 < 2 * self.n - 1 {
                self.lazy_data[2 * index + 1] =
                    ME::operate(self.lazy_data[2 * index + 1], self.lazy_data[index]);
                self.lazy_data[2 * index + 2] =
                    ME::operate(self.lazy_data[2 * index + 2], self.lazy_data[index]);
            }
            self.data[index] = A::operate(
                self.data[index],
                P::multi_operate(self.lazy_data[index], len),
            );
            self.lazy_data[index] = ME::identity();
        }
        pub fn update(&mut self, l: usize, r: usize, val: E) {
            let n = self.n;
            self._update(l, r, 0, 0, n, val);
        }
        fn _update(&mut self, ql: usize, qr: usize, index: usize, l: usize, r: usize, val: E) -> T {
            self.evaluate(r - l, index);
            if r <= ql || qr <= l {
                return self.data[index];
            }
            if ql <= l && r <= qr {
                self.lazy_data[index] = ME::operate(self.lazy_data[index], val);
                return A::operate(self.data[index], self.lazy_data[index]);
            }
            self.data[index] = MT::operate(
                self._update(ql, qr, 2 * index + 1, l, (l + r) / 2, val),
                self._update(ql, qr, 2 * index + 2, (l + r) / 2, r, val),
            );
            self.data[index]
        }
        pub fn get(&mut self, l: usize, r: usize) -> T {
            let n = self.n;
            self._get(l, r, 0, 0, n)
        }
        fn _get(&mut self, ql: usize, qr: usize, index: usize, l: usize, r: usize) -> T {
            self.evaluate(r - l, index);
            if r <= ql || qr <= l {
                return MT::identity();
            }
            if ql <= l && r <= qr {
                return self.data[index];
            }
            let vl = self._get(ql, qr, 2 * index + 1, l, (l + r) / 2);
            let vr = self._get(ql, qr, 2 * index + 2, (l + r) / 2, r);
            MT::operate(vl, vr)
        }
    }
}

const INF: usize = 1_000_000_000_000_000;

struct IMonoidT;
impl Monoid<usize> for IMonoidT {
    fn identity() -> usize {
        INF
    }
}
impl Magma<usize> for IMonoidT {
    fn operate(lhs: usize, rhs: usize) -> usize {
        min!(lhs, rhs)
    }
}
impl SemiGroup<usize> for IMonoidT {}

struct IMonoidE;
impl Monoid<usize> for IMonoidE {
    fn identity() -> usize {
        INF
    }
}
impl Magma<usize> for IMonoidE {
    fn operate(lhs: usize, rhs: usize) -> usize {
        min!(lhs, rhs)
    }
}
impl SemiGroup<usize> for IMonoidE {}

struct IEffection {}
impl Effection<usize, usize> for IEffection {
    fn operate(element: usize, effector: usize) -> usize {
        min!(element, effector)
    }
}
struct IMultiOperator;
impl MultiOperator<usize> for IMultiOperator {
    fn multi_operate(element: usize, num: usize) -> usize {
        element
    }
}

fn solve() {
    let (n, m) = get!(usize, usize);
    let mut lrc = get!(usize, usize, usize; m);

    lrc.sort();

    let mut tree =
        LazySegmentTree::<usize, IMonoidT, usize, IMonoidE, IEffection, IMultiOperator>::new(n + 1);

    tree.update(1, 2, 0);
    for (l, r, c) in lrc {
        let v = tree.get(l, r + 1);
        tree.update(l, r + 1, v + c);
    }
    let v = tree.get(n, n + 1);
    if v == INF {
        println!("-1");
    } else {
        println!("{}", v);
    }
}


Measured memory_bytes: 16636