#![allow(unused)]

// ///////////////
// Lazy SegTree //
// ///////////////

// struct Delta {
//     value: Modulo,
//     mask: usize,
// }
//
// impl Default for Delta {
//     fn default() -> Self {
//         Self {
//             value: Modulo::new(1),
//             mask: 0,
//         }
//     }
// }
//
// impl Delta {
//     fn new(value: Modulo, mask: usize) -> Self {
//         Self { value, mask }
//     }
// }
//
// impl std::ops::Add for Delta {
//     type Output = Self;
//
//     fn add(self, rhs: Self) -> Self::Output {
//         let value = self.value * rhs.value;
//         let mask = self.mask | rhs.mask;
//         Self { value, mask }
//     }
// }
//
// #[derive(Default, Copy, Clone)]
// struct Node {
//     value: Modulo,
//     mask: usize,
//     size: usize,
// }
//
// impl Node {
//     fn new(value: Modulo) -> Self {
//         Self {
//             value,
//             mask: 0,
//             size: 1,
//         }
//     }
//     fn new_by_child(l: Self, r: Self) -> Self {
//         Self {
//             value: l.value + r.value,
//             mask: l.mask | r.mask,
//             size: l.size + r.size,
//         }
//     }
// }

use proconio::marker::Usize1;

struct LazySegTree<Node, Delta, NodeMerge, ApplyDelta, UpdateDelta> {
    n: usize,
    tree_height: usize,
    tree: Vec<Node>,
    lazy_delta: Vec<Delta>,
    node_init: Node,
    delta_init: Delta,
    node_merge: NodeMerge,
    apply_delta: ApplyDelta,
    update_delta: UpdateDelta,
    dirty: Vec<bool>,
}

impl<Node, Delta, NodeMerge, ApplyDelta, UpdateDelta>
    LazySegTree<Node, Delta, NodeMerge, ApplyDelta, UpdateDelta>
where
    Node: Copy,
    Delta: Copy,
    NodeMerge: Fn(Node, Node) -> Node,
    ApplyDelta: Fn(Node, Delta) -> Node,
    UpdateDelta: Fn(Delta, Delta) -> Delta,
{
    fn new(
        n: usize,
        node_init: Node,
        delta_init: Delta,
        node_merge: NodeMerge,
        apply_delta: ApplyDelta,
        update_delta: UpdateDelta,
    ) -> Self {
        let mut tree_height = 0;
        while (1 << tree_height) < n {
            tree_height += 1;
        }
        let mut tree = vec![node_init; n * 2];
        for i in (1..n).rev() {
            tree[i] = (node_merge)(tree[i * 2], tree[i * 2 + 1]);
        }

        Self {
            n,
            tree_height,
            tree,
            lazy_delta: vec![delta_init; n],
            node_init,
            delta_init,
            node_merge,
            apply_delta,
            update_delta,
            dirty: vec![false; n],
        }
    }

    // 1. update Delta for Node
    // 2. Delta accumulate
    fn apply(&mut self, i: usize, delta: Delta) {
        self.tree[i] = (self.apply_delta)(self.tree[i], delta);
        if i < self.n {
            self.lazy_delta[i] = (self.update_delta)(self.lazy_delta[i], delta);
            self.dirty[i] = true;
        }
    }

    fn query(&mut self, l: usize, r: usize) -> Node {
        if l >= r {
            return self.node_init;
        }
        let mut l = l + self.n;
        let mut r = r + self.n;
        self.propagate(l);
        self.propagate(r - 1);
        let mut lp = self.node_init;
        let mut rp = self.node_init;
        while l < r {
            if l & 1 == 1 {
                lp = (self.node_merge)(lp, self.tree[l]);
                l += 1;
            }
            if r & 1 == 1 {
                r -= 1;
                rp = (self.node_merge)(self.tree[r], rp);
            }
            l /= 2;
            r /= 2;
        }
        (self.node_merge)(lp, rp)
    }

    fn update(&mut self, l: usize, r: usize, delta: Delta) {
        if l >= r {
            return;
        }

        let mut l = l + self.n;
        let mut r = r + self.n;

        self.propagate(l);
        self.propagate(r - 1);
        let origin_l = l.clone();
        let origin_r = r.clone();

        while l < r {
            if l & 1 == 1 {
                self.apply(l, delta);
                l += 1;
            }
            if r & 1 == 1 {
                r -= 1;

                self.apply(r, delta);
            }
            l /= 2;
            r /= 2;
        }
        self.build(origin_l);
        self.build(origin_r - 1);
    }

    fn build(&mut self, node: usize) {
        let mut i = node / 2;
        while i > 0 {
            self.tree[i] = (self.node_merge)(self.tree[i * 2], self.tree[i * 2 + 1]);
            if self.dirty[i] {
                self.tree[i] = (self.apply_delta)(self.tree[i], self.lazy_delta[i]);
            }
            i /= 2;
        }
    }

    fn propagate(&mut self, node: usize) {
        for h in (1..=self.tree_height).rev() {
            let i = node >> h;
            if self.dirty[i] {
                self.apply(i * 2, self.lazy_delta[i]);
                self.apply(i * 2 + 1, self.lazy_delta[i]);
                self.lazy_delta[i] = self.delta_init;
                self.dirty[i] = false;
            }
        }
    }
}

fn main() {
    use proconio::*;
    input! {
    n: usize,
    m: usize,
    a: [(Usize1, Usize1, i64); m]
    }
    let mut q = vec![vec![]; n];
    for (l, r, a) in a {
        q[r].push((l, a));
    }
    let f = std::cmp::max;
    let g = |a: i64, b: i64| a + b;
    let h = |a: i64, b: i64| a + b;

    let mut tree = LazySegTree::new(n, 0, 0, f, g, h);

    for r in 0..n {
        let value = tree.query(0, r);
        tree.update(r, r + 1, value);

        for &(l, a) in &q[r] {
            tree.update(l, r + 1, a);
        }
    }
    let ans = tree.query(0, n);
    println!("{:?}", ans);
}


Measured memory_bytes: 22272