Problem:
Score : 500 points

Problem Statement

There are K items placed on a grid of squares with R rows and C columns. Let (i, j) denote the square at the i-th row (1 \leq i \leq R) and the j-th column (1 \leq j \leq C). The i-th item is at (r_i, c_i) and has the value v_i.

Takahashi will begin at (1, 1), the start, and get to (R, C), the goal. When he is at (i, j), he can move to (i + 1, j) or (i, j + 1) (but cannot move to a non-existent square).

He can pick up items on the squares he visits, including the start and the goal, but at most three for each row. It is allowed to ignore the item on a square he visits.

Find the maximum possible sum of the values of items he picks up.

Constraints

1 \leq R, C \leq 3000

1 \leq K \leq \min(2 \times 10^5, R \times C)

1 \leq r_i \leq R

1 \leq c_i \leq C

(r_i, c_i) \neq (r_j, c_j) (i \neq j)

1 \leq v_i \leq 10^9

All values in input are integers.

Input

Input is given from Standard Input in the following format:

R C K
r_1 c_1 v_1
r_2 c_2 v_2
:
r_K c_K v_K

Output

Print the maximum possible sum of the values of items Takahashi picks up.

Sample Input 1

2 2 3
1 1 3
2 1 4
1 2 5

Sample Output 1

8

He has two ways to get to the goal:

Visit (1, 1), (1, 2), and (2, 2), in this order. In this case, the total value of the items he can pick up is 3 + 5 = 8.

Visit (1, 1), (2, 1), and (2, 2), in this order. In this case, the total value of the items he can pick up is 3 + 4 = 7.

Thus, the maximum possible sum of the values of items he picks up is 8.

Sample Input 2

2 5 5
1 1 3
2 4 20
1 2 1
1 3 4
1 4 2

Sample Output 2

29

We have four items in the 1-st row. The optimal choices are as follows:

Visit (1, 1) (1, 2), (1, 3), (1, 4), (2, 4), and (2, 5), in this order, and pick up all items except the one on (1, 2). Then, the total value of the items he picks up will be 3 + 4 + 2 + 20 = 29.

Sample Input 3

4 5 10
2 5 12
1 5 12
2 3 15
1 2 20
1 1 28
2 4 26
3 2 27
4 5 21
3 5 10
1 3 10

Sample Output 3

142

Solution in Rust (1.42.0) (judge verdict: Accepted)

// SNIPPET read
pub trait Readable {
    type Output;
    const WORD_COUNT: usize;
    fn read_words(words: &[&str]) -> Result<Self::Output, String>;
}
#[macro_export]
macro_rules! readable {
    ( $t:ty, $words_count:expr, |$words:ident| $read_words:expr ) => {
        impl Readable for $t {
            type Output = $t;
            const WORD_COUNT: usize = $words_count;
            fn read_words($words: &[&str]) -> Result<$t, String> {
                Ok($read_words)
            }
        }
    };
}
readable!((), 1, |_ss| ());
readable!(String, 1, |ss| ss[0].to_string());
impl Readable for char {
    type Output = char;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<char, String> {
        let chars: Vec<char> = words[0].chars().collect();
        if chars.len() == 1 {
            Ok(chars[0])
        } else {
            Err(format!("cannot parse `{}` as a char", words[0]))
        }
    }
}
pub struct Chars();
impl Readable for Chars {
    type Output = Vec<char>;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<Vec<char>, String> {
        Ok(words[0].chars().collect())
    }
}
pub struct Bytes();
impl Readable for Bytes {
    type Output = Vec<u8>;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<Vec<u8>, String> {
        Ok(words[0].bytes().collect())
    }
}
impl Readable for i8 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<i8, String> {
        use std::str::FromStr;
        i8::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as i8", words[0])
        })
    }
}
impl Readable for u8 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<u8, String> {
        use std::str::FromStr;
        u8::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as u8", words[0])
        })
    }
}
impl Readable for i16 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<i16, String> {
        use std::str::FromStr;
        i16::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as i16", words[0])
        })
    }
}
impl Readable for u16 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<u16, String> {
        use std::str::FromStr;
        u16::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as u16", words[0])
        })
    }
}
impl Readable for i32 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<i32, String> {
        use std::str::FromStr;
        i32::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as i32", words[0])
        })
    }
}
impl Readable for u32 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<u32, String> {
        use std::str::FromStr;
        u32::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as u32", words[0])
        })
    }
}
impl Readable for i64 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<i64, String> {
        use std::str::FromStr;
        i64::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as i64", words[0])
        })
    }
}
impl Readable for u64 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<u64, String> {
        use std::str::FromStr;
        u64::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as u64", words[0])
        })
    }
}
impl Readable for i128 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<i128, String> {
        use std::str::FromStr;
        i128::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as i64", words[0])
        })
    }
}
impl Readable for u128 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<u128, String> {
        use std::str::FromStr;
        u128::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as u64", words[0])
        })
    }
}
impl Readable for isize {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<isize, String> {
        use std::str::FromStr;
        <isize>::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as isize", words[0])
        })
    }
}
impl Readable for usize {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<usize, String> {
        use std::str::FromStr;
        <usize>::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as usize", words[0])
        })
    }
}
impl Readable for f32 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<f32, String> {
        use std::str::FromStr;
        f32::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as f32", words[0])
        })
    }
}
impl Readable for f64 {
    type Output = Self;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<f64, String> {
        use std::str::FromStr;
        f64::from_str(words[0]).map_err(|_| {
            format!("cannot parse `{}` as f64", words[0])
        })
    }
}
#[allow(non_camel_case_types)]
pub struct u8_;
impl Readable for u8_ {
    type Output = u8;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        u8::read_words(words).map(|n| n-1)
    }
}
#[allow(non_camel_case_types)]
pub struct u16_;
impl Readable for u16_ {
    type Output = u16;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        u16::read_words(words).map(|n| n-1)
    }
}
#[allow(non_camel_case_types)]
pub struct u32_;
impl Readable for u32_ {
    type Output = u32;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        u32::read_words(words).map(|n| n-1)
    }
}
#[allow(non_camel_case_types)]
pub struct u64_;
impl Readable for u64_ {
    type Output = u64;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        u64::read_words(words).map(|n| n-1)
    }
}
#[allow(non_camel_case_types)]
pub struct usize_;
impl Readable for usize_ {
    type Output = usize;
    const WORD_COUNT: usize = 1;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        <usize>::read_words(words).map(|n| n-1)
    }
}
impl<T1: Readable, T2: Readable> Readable for (T1, T2) {
    type Output = (T1::Output, T2::Output);
    const WORD_COUNT: usize = T1::WORD_COUNT + T2::WORD_COUNT;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let mut start = 0;
        let count1 = T1::WORD_COUNT;
        let val1 = T1::read_words(&words[start .. start+count1])?;
        start += count1;
        let val2 = T2::read_words(&words[start..])?;
        Ok((val1, val2))
    }
}
impl<T1: Readable, T2: Readable, T3: Readable> Readable for (T1, T2, T3) {
    type Output = (T1::Output, T2::Output, T3::Output);
    const WORD_COUNT: usize = T1::WORD_COUNT + T2::WORD_COUNT + T3::WORD_COUNT;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let mut start = 0;
        let count1 = T1::WORD_COUNT;
        let val1 = T1::read_words(&words[start .. start+count1])?;
        start += count1;
        let count2 = T2::WORD_COUNT;
        let val2 = T2::read_words(&words[start .. start+count2])?;
        start += count2;
        let val3 = T3::read_words(&words[start..])?;
        Ok((val1, val2, val3))
    }
}
impl<T1: Readable, T2: Readable, T3: Readable, T4: Readable> Readable for (T1, T2, T3, T4) {
    type Output = (T1::Output, T2::Output, T3::Output, T4::Output);
    const WORD_COUNT: usize = T1::WORD_COUNT + T2::WORD_COUNT + T3::WORD_COUNT + T4::WORD_COUNT;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let mut start = 0;
        let count1 = T1::WORD_COUNT;
        let val1 = T1::read_words(&words[start .. start+count1])?;
        start += count1;
        let count2 = T2::WORD_COUNT;
        let val2 = T2::read_words(&words[start .. start+count2])?;
        start += count2;
        let count3 = T3::WORD_COUNT;
        let val3 = T3::read_words(&words[start .. start+count3])?;
        start += count3;
        let val4 = T4::read_words(&words[start..])?;
        Ok((val1, val2, val3, val4))
    }
}
impl<T1: Readable, T2: Readable, T3: Readable, T4: Readable, T5: Readable> Readable for (T1, T2, T3, T4, T5) {
    type Output = (T1::Output, T2::Output, T3::Output, T4::Output, T5::Output);
    const WORD_COUNT: usize = T1::WORD_COUNT + T2::WORD_COUNT + T3::WORD_COUNT + T4::WORD_COUNT + T5::WORD_COUNT;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let mut start = 0;
        let count1 = T1::WORD_COUNT;
        let val1 = T1::read_words(&words[start .. start+count1])?;
        start += count1;
        let count2 = T2::WORD_COUNT;
        let val2 = T2::read_words(&words[start .. start+count2])?;
        start += count2;
        let count3 = T3::WORD_COUNT;
        let val3 = T3::read_words(&words[start .. start+count3])?;
        start += count3;
        let count4 = T4::WORD_COUNT;
        let val4 = T4::read_words(&words[start .. start+count4])?;
        start += count4;
        let val5 = T5::read_words(&words[start..])?;
        Ok((val1, val2, val3, val4, val5))
    }
}
impl<T1: Readable, T2: Readable, T3: Readable, T4: Readable, T5: Readable, T6: Readable> Readable for (T1, T2, T3, T4, T5, T6) {
    type Output = (T1::Output, T2::Output, T3::Output, T4::Output, T5::Output, T6::Output);
    const WORD_COUNT: usize = T1::WORD_COUNT + T2::WORD_COUNT + T3::WORD_COUNT + T4::WORD_COUNT + T5::WORD_COUNT + T6::WORD_COUNT;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let mut start = 0;
        let count1 = T1::WORD_COUNT;
        let val1 = T1::read_words(&words[start .. start+count1])?;
        start += count1;
        let count2 = T2::WORD_COUNT;
        let val2 = T2::read_words(&words[start .. start+count2])?;
        start += count2;
        let count3 = T3::WORD_COUNT;
        let val3 = T3::read_words(&words[start .. start+count3])?;
        start += count3;
        let count4 = T4::WORD_COUNT;
        let val4 = T4::read_words(&words[start .. start+count4])?;
        start += count4;
        let count5 = T5::WORD_COUNT;
        let val5 = T5::read_words(&words[start .. start+count5])?;
        start += count5;
        let val6 = T6::read_words(&words[start..])?;
        Ok((val1, val2, val3, val4, val5, val6))
    }
}
impl<T: Readable> Readable for [T; 2] {
    type Output = [T::Output; 2];
    const WORD_COUNT: usize = T::WORD_COUNT * 2;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let val1 = T::read_words(&words[T::WORD_COUNT*0 .. T::WORD_COUNT*1])?;
        let val2 = T::read_words(&words[T::WORD_COUNT*1 .. T::WORD_COUNT*2])?;
        Ok([val1, val2])
    }
}
impl<T: Readable> Readable for [T; 3] {
    type Output = [T::Output; 3];
    const WORD_COUNT: usize = T::WORD_COUNT * 3;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let val1 = T::read_words(&words[T::WORD_COUNT*0 .. T::WORD_COUNT*1])?;
        let val2 = T::read_words(&words[T::WORD_COUNT*1 .. T::WORD_COUNT*2])?;
        let val3 = T::read_words(&words[T::WORD_COUNT*2 .. T::WORD_COUNT*3])?;
        Ok([val1, val2, val3])
    }
}
impl<T: Readable> Readable for [T; 4] {
    type Output = [T::Output; 4];
    const WORD_COUNT: usize = T::WORD_COUNT * 4;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let val1 = T::read_words(&words[T::WORD_COUNT*0 .. T::WORD_COUNT*1])?;
        let val2 = T::read_words(&words[T::WORD_COUNT*1 .. T::WORD_COUNT*2])?;
        let val3 = T::read_words(&words[T::WORD_COUNT*2 .. T::WORD_COUNT*3])?;
        let val4 = T::read_words(&words[T::WORD_COUNT*3 .. T::WORD_COUNT*4])?;
        Ok([val1, val2, val3, val4])
    }
}
impl<T: Readable> Readable for [T; 5] {
    type Output = [T::Output; 5];
    const WORD_COUNT: usize = T::WORD_COUNT * 5;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let val1 = T::read_words(&words[T::WORD_COUNT*0 .. T::WORD_COUNT*1])?;
        let val2 = T::read_words(&words[T::WORD_COUNT*1 .. T::WORD_COUNT*2])?;
        let val3 = T::read_words(&words[T::WORD_COUNT*2 .. T::WORD_COUNT*3])?;
        let val4 = T::read_words(&words[T::WORD_COUNT*3 .. T::WORD_COUNT*4])?;
        let val5 = T::read_words(&words[T::WORD_COUNT*4 .. T::WORD_COUNT*5])?;
        Ok([val1, val2, val3, val4, val5])
    }
}
impl<T: Readable> Readable for [T; 6] {
    type Output = [T::Output; 6];
    const WORD_COUNT: usize = T::WORD_COUNT * 6;
    fn read_words(words: &[&str]) -> Result<Self::Output, String> {
        assert_eq!(words.len(), Self::WORD_COUNT);
        let val1 = T::read_words(&words[T::WORD_COUNT*0 .. T::WORD_COUNT*1])?;
        let val2 = T::read_words(&words[T::WORD_COUNT*1 .. T::WORD_COUNT*2])?;
        let val3 = T::read_words(&words[T::WORD_COUNT*2 .. T::WORD_COUNT*3])?;
        let val4 = T::read_words(&words[T::WORD_COUNT*3 .. T::WORD_COUNT*4])?;
        let val5 = T::read_words(&words[T::WORD_COUNT*4 .. T::WORD_COUNT*5])?;
        let val6 = T::read_words(&words[T::WORD_COUNT*5 .. T::WORD_COUNT*6])?;
        Ok([val1, val2, val3, val4, val5, val6])
    }
}
pub trait ReadableFromLine {
    type Output;
    fn read_line(line: &str) -> Result<Self::Output, String>;
}
fn split_into_words(line: &str) -> Vec<&str> {
    line.trim_end_matches('\n').split_whitespace().collect()
}
impl<T: Readable> ReadableFromLine for T {
    type Output = T::Output;
    fn read_line(line: &str) -> Result<T::Output, String> {
        let words = split_into_words(line);
        if words.len() != T::WORD_COUNT {
            return Err(format!("line `{}` has {} words, expected {}",
                               line, words.len(), T::WORD_COUNT));
        }
        T::read_words(&words)
    }
}
pub fn read_words_into_vec<T: Readable>(words: &[&str], line: &str) -> Result<Vec<T::Output>, String> {
    let n = T::WORD_COUNT;
    assert_eq!(words.len() % n, 0);
    let mut result = Vec::new();
    for chunk in words.chunks(n) {
        match T::read_words(chunk) {
            Ok(v) => result.push(v),
            Err(msg) => {
                let fragment_msg = if n == 1 {
                    format!("word {}", result.len())
                } else {
                    let l = result.len();
                    format!("words {}-{}", n*l + 1, (n+1) * l)
                };
                return Err(format!(
                    "{} of line `{}`: {}", fragment_msg, line, msg
                ));
            }
        }
    }
    Ok(result)
}
pub fn split_into_words_for_collection<T: Readable>(
    line: &str, prefix_words_count: usize
) -> Result<Vec<&str>, String> {
    let n = T::WORD_COUNT;
    let words = split_into_words(line);
    if words.len() < prefix_words_count {
        return Err(
            format!("line `{}` has {} words, expected at least {}",
                    line, words.len(), prefix_words_count)
        );
    }
    if (words.len() - prefix_words_count) % T::WORD_COUNT != 0 {
        return Err(
            format!("line `{}` has {} words, expected {} + {}",
                    line, words.len(), prefix_words_count, n)
        );
    }
    Ok(words)
}
#[macro_export]
macro_rules! readable_collection {
    ($u:ident => $collection_in:ty, $collection_out:ty) => {
        readable_collection!($u: => $collection_in, $collection_out);
    };
    ($u:ident : $( $bound:path ),* => $collection_in:ty, $collection_out:ty) => {
        impl<$u: Readable> ReadableFromLine for $collection_in
        where
            <$u as Readable>::Output: Sized $(+ $bound)*
        {
            type Output = $collection_out;
            fn read_line(line: &str) -> Result<Self::Output, String> {
                let words = split_into_words_for_collection::<$u>(line, 0)?;
                Ok(read_words_into_vec::<$u>(&words, line)?.into_iter().collect())
            }
        }
        impl<T1: Readable, $u: Readable> ReadableFromLine for (T1, $collection_in)
        where
            <$u as Readable>::Output: Sized $(+ $bound)*
        {
            type Output = (T1::Output, $collection_out);
            fn read_line(line: &str) -> Result<Self::Output, String> {
                let prefix_len = T1::WORD_COUNT;
                let words = split_into_words_for_collection::<$u>(line, prefix_len)?;
                let val1 = T1::read_words(&words[..prefix_len])?;
                let rest = read_words_into_vec::<$u>(&words[prefix_len..], line)?;
                Ok((val1, rest.into_iter().collect()))
            }
        }
        impl<T1: Readable, T2: Readable, $u: Readable> ReadableFromLine for (T1, T2, $collection_in)
        where
            <$u as Readable>::Output: Sized $(+ $bound)*
        {
            type Output = (T1::Output, T2::Output, $collection_out);
            fn read_line(line: &str) -> Result<Self::Output, String> {
                let prefix_len = <(T1, T2)>::WORD_COUNT;
                let words = split_into_words_for_collection::<$u>(line, prefix_len)?;
                let mut start = 0;
                let count1 = T1::WORD_COUNT;
                let val1 = T1::read_words(&words[start .. start+count1])?;
                start += count1;
                let count2 = T2::WORD_COUNT;
                let val2 = T2::read_words(&words[start .. start+count2])?;
                let rest = read_words_into_vec::<$u>(&words[prefix_len..], line)?;
                Ok((val1, val2, rest.into_iter().collect()))
            }
        }
        impl<T1: Readable, T2: Readable, T3: Readable, $u: Readable> ReadableFromLine for (T1, T2, T3, $collection_in)
        where
            <$u as Readable>::Output: Sized $(+ $bound)*
        {
            type Output = (T1::Output, T2::Output, T3::Output, $collection_out);
            fn read_line(line: &str) -> Result<Self::Output, String> {
                let prefix_len = <(T1, T2, T3)>::WORD_COUNT;
                let words = split_into_words_for_collection::<$u>(line, prefix_len)?;
                let mut start = 0;
                let count1 = T1::WORD_COUNT;
                let val1 = T1::read_words(&words[start .. start+count1])?;
                start += count1;
                let count2 = T2::WORD_COUNT;
                let val2 = T2::read_words(&words[start .. start+count2])?;
                start += count2;
                let count3 = T3::WORD_COUNT;
                let val3 = T3::read_words(&words[start .. start+count3])?;
                let rest = read_words_into_vec::<$u>(&words[prefix_len..], line)?;
                Ok((val1, val2, val3, rest.into_iter().collect()))
            }
        }
        impl<T1: Readable, T2: Readable, T3: Readable, T4: Readable, $u: Readable> ReadableFromLine for (T1, T2, T3, T4, $collection_in)
        where
            <$u as Readable>::Output: Sized $(+ $bound)*
        {
            type Output = (T1::Output, T2::Output, T3::Output, T4::Output, $collection_out);
            fn read_line(line: &str) -> Result<Self::Output, String> {
                let prefix_len = <(T1, T2, T3, T4)>::WORD_COUNT;
                let words = split_into_words_for_collection::<$u>(line, prefix_len)?;
                let mut start = 0;
                let count1 = T1::WORD_COUNT;
                let val1 = T1::read_words(&words[start .. start+count1])?;
                start += count1;
                let count2 = T2::WORD_COUNT;
                let val2 = T2::read_words(&words[start .. start+count2])?;
                start += count2;
                let count3 = T3::WORD_COUNT;
                let val3 = T3::read_words(&words[start .. start+count3])?;
                start += count3;
                let count4 = T4::WORD_COUNT;
                let val4 = T4::read_words(&words[start .. start+count4])?;
                let rest = read_words_into_vec::<$u>(&words[prefix_len..], line)?;
                Ok((val1, val2, val3, val4, rest.into_iter().collect()))
            }
        }
    };
}
readable_collection!(U => Vec<U>, Vec<U::Output>);
pub fn read<T: ReadableFromLine>() -> T::Output {
    let mut line = String::new();
    std::io::stdin().read_line(&mut line).unwrap();
    T::read_line(&line).unwrap()
}
#[macro_export]
macro_rules! read {
    () => {
        let mut line = String::new();
        std::io::stdin().read_line(&mut line).unwrap();
    };
    ( $pat:pat = $t:ty $(,)* ) => {
        let $pat = read::<$t>();
    };
    ( ! $(,)* ) => {
        let _ = read::<()>();
    };
    ( $pat:pat = $t:ty, $( $rest:tt )+ ) => {
        read_inner!($pat = $t; $($rest)+);
    };
    ( !, $( $rest:tt )+ ) => {
        read_inner!(_ = (); $($rest)+);
    };
}
#[macro_export]
#[doc(hidden)]
macro_rules! read_inner {
    ( $( $acc_pat:pat = $acc_t:ty ),+ ; $pat:pat = $t:ty, $( $rest:tt )* ) => {
        read_inner!($( $acc_pat = $acc_t ),+ , $pat = $t ; $($rest)*);
    };
    ( $( $acc_pat:pat = $acc_t:ty ),+ ; !, $( $rest:tt )* ) => {
        read_inner!($( $acc_pat = $acc_t ),+ , _ = () ; $($rest)*);
    };
    ( $( $acc_pat:pat = $acc_t:ty ),+ ; $pat:pat = $t:ty ) => {
        read_inner!($( $acc_pat = $acc_t ),+ , $pat = $t ;);
    };
    ( $( $acc_pat:pat = $acc_t:ty ),+ ; ! ) => {
        read_inner!($( $acc_pat = $acc_t ),+ , _ = () ;);
    };
    ( $( $pat:pat = $t:ty ),+ ; ) => {
        let ($($pat),+) = read::<($($t),+)>();
    };
}
pub trait ReadableFromChunk {
    type Output;
    fn lines_count() -> usize;
    fn read_chunk(lines: &[String]) -> Result<Self::Output, String>;
}
impl<T1: ReadableFromLine, T2: ReadableFromLine> ReadableFromChunk for (T1, T2) {
    type Output = (T1::Output, T2::Output);
    fn lines_count() -> usize { 2 }
    fn read_chunk(lines: &[String]) -> Result<Self::Output, String> {
        let out1 = T1::read_line(&lines[0])?;
        let out2 = T2::read_line(&lines[1])?;
        Ok((out1, out2))
    }
}
impl<T1: ReadableFromLine, T2: ReadableFromLine, T3: ReadableFromLine> ReadableFromChunk for (T1, T2, T3) {
    type Output = (T1::Output, T2::Output, T3::Output);
    fn lines_count() -> usize { 3 }
    fn read_chunk(lines: &[String]) -> Result<Self::Output, String> {
        let out1 = T1::read_line(&lines[0])?;
        let out2 = T2::read_line(&lines[1])?;
        let out3 = T3::read_line(&lines[2])?;
        Ok((out1, out2, out3))
    }
}
impl<T1: ReadableFromLine, T2: ReadableFromLine, T3: ReadableFromLine, T4: ReadableFromLine> ReadableFromChunk for (T1, T2, T3, T4) {
    type Output = (T1::Output, T2::Output, T3::Output, T4::Output);
    fn lines_count() -> usize { 4 }
    fn read_chunk(lines: &[String]) -> Result<Self::Output, String> {
        let out1 = T1::read_line(&lines[0])?;
        let out2 = T2::read_line(&lines[1])?;
        let out3 = T3::read_line(&lines[2])?;
        let out4 = T4::read_line(&lines[3])?;
        Ok((out1, out2, out3, out4))
    }
}
pub fn read_chunk<T: ReadableFromChunk>() -> T::Output {
    let stdin = std::io::stdin();
    let mut handle = stdin.lock();
    read_chunk_from_handle::<T>(&mut handle).unwrap()
}
fn read_chunk_from_handle<T: ReadableFromChunk>(handle: &mut std::io::StdinLock) -> Option<T::Output> {
    use std::io::BufRead;
    let mut lines = vec![String::new(); T::lines_count()];
    let mut first = true;
    for line in &mut lines {
        if handle.read_line(line).unwrap() == 0 && first {
            return None;
        }
        first = false;
    }
    Some(T::read_chunk(&lines).unwrap())
}
#[macro_export]
macro_rules! read_chunk {
    ( $( $pat:pat = $t:ty ),+ ) => {
        let ($($pat),+) = read_chunk::<($($t),+)>();
    };
}
static mut STDIN: Option<std::io::Stdin> = None;
pub struct ReadLines<T: ReadableFromLine> {
    lock: std::io::StdinLock<'static>,
    phantom: std::marker::PhantomData<T>
}
impl<T: ReadableFromLine> Iterator for ReadLines<T> {
    type Item = T::Output;
    fn next(&mut self) -> Option<T::Output> {
        use std::io::BufRead;
        let mut line = String::new();
        if self.lock.read_line(&mut line).unwrap() > 0 {
            Some(T::read_line(&line).unwrap())
        } else {
            None
        }
    }
}
pub fn read_lines<T: ReadableFromLine>() -> ReadLines<T> {
    unsafe {
        if STDIN.is_none() {
            STDIN = Some(std::io::stdin());
        }
    }
    ReadLines {
        lock: unsafe { STDIN.as_ref().unwrap().lock() },
        phantom: std::marker::PhantomData::<T>
    }
}
pub struct ReadChunks<T: ReadableFromChunk> {
    lock: std::io::StdinLock<'static>,
    phantom: std::marker::PhantomData<T>
}
impl<T: ReadableFromChunk> Iterator for ReadChunks<T> {
    type Item = T::Output;
    fn next(&mut self) -> Option<T::Output> {
        read_chunk_from_handle::<T>(&mut self.lock)
    }
}
pub fn read_chunks<T: ReadableFromChunk>() -> ReadChunks<T> {
    unsafe {
        if STDIN.is_none() {
            STDIN = Some(std::io::stdin());
        }
    }
    ReadChunks {
        lock: unsafe { STDIN.as_ref().unwrap().lock() },
        phantom: std::marker::PhantomData::<T>
    }
}
pub trait Words {
    fn read<T: Readable>(&self) -> T::Output;
}
impl<'a> Words for [&'a str] {
    fn read<T: Readable>(&self) -> T::Output {
        T::read_words(self).unwrap()
    }
}
impl<'a> Words for &'a str {
    fn read<T: Readable>(&self) -> T::Output {
        T::read_words(&[self]).unwrap()
    }
}

// SNIPPET utils
#[macro_export]
macro_rules! echo {
    () => {
        println!()
    };
    ($e: expr $(,)?) => {
        println!("{}", $e)
    };
    ($e: expr, $($es: expr),+ $(,)?) => {
        {
            use std::io::Write;
            let stdout = std::io::stdout();
            let mut handle = stdout.lock();
            write!(handle, "{}", $e).unwrap();
            $(
                write!(handle, " {}", $es).unwrap();
            )+
            writeln!(handle).unwrap();
        }
    };
}
pub fn yn(result: bool) {
    if result {
        println!("Yes");
    } else {
        println!("No");
    }
}
#[allow(non_snake_case)]
pub fn YN(result: bool) {
    if result {
        println!("YES");
    } else {
        println!("NO");
    }
}
pub fn exit(msg: impl std::fmt::Display) -> ! {
    println!("{}", msg);
    std::process::exit(0)
}
#[macro_export]
#[cfg(local)]
macro_rules! dbg {
    () => {
        {
            use std::io::{self, Write};
            writeln!(io::stderr(), "{}: dbg", line!()).unwrap();
        }
    };
    ($e: expr) => {
        {
            use std::io::{self, Write};
            let result = $e;
            writeln!(io::stderr(), "{}: {} = {:?}",
                     line!(), stringify!($e), result)
                .unwrap();
            result
        }
    }
}
#[macro_export]
#[cfg(not(local))]
macro_rules! dbg {
    () => {};
    ($e: expr) => {
        { $e }
    }
}

// SNIPPET option
pub trait BoolExt {
    fn then<T>(self, value: T) -> Option<T>;
    fn then_with<T, F>(self, f: F) -> Option<T> where F: FnOnce() -> T;
    fn and<T>(self, option: Option<T>) -> Option<T>;
    fn and_then<T, F>(self, f: F) -> Option<T> where F: FnOnce() -> Option<T>;
}
impl BoolExt for bool {
    fn then<T>(self, value: T) -> Option<T> {
        if self { Some(value) } else { None }
    }
    fn then_with<T, F>(self, f: F) -> Option<T> where F: FnOnce() -> T {
        if self { Some(f()) } else { None }
    }
    fn and<T>(self, option: Option<T>) -> Option<T> {
        if self { option } else { None }
    }
    fn and_then<T, F>(self, f: F) -> Option<T> where F: FnOnce() -> Option<T> {
        if self { f() } else { None }
    }
}
pub trait OptionExt<T> {
    fn to_string_or<U: std::fmt::Display>(&self, default: U) -> String
    where
        T: std::fmt::Display;
}
impl<T> OptionExt<T> for Option<T> {
    fn to_string_or<U: std::fmt::Display>(&self, default: U) -> String
    where
        T: std::fmt::Display
    {
        self.as_ref().map(|x| x.to_string()).unwrap_or(default.to_string())
    }
    /*
    fn get_or_insert_with<F: FnOnce() -> T>(&mut self, f: F) -> &mut T {
        match *self {
            None => *self = Some(f()),
            _ => ()
        }
        self.as_mut().unwrap()
    }
    */
}
pub trait Guard: Sized {
    fn guard(self, pred: impl FnOnce(&Self) -> bool) -> Option<Self>;
}
impl<T> Guard for T {
    fn guard(self, pred: impl FnOnce(&T) -> bool) -> Option<T> {
        if pred(&self) { Some(self) } else { None }
    }
}

// SNIPPET num_types
pub trait WithZero: Sized +
    for<'a> std::ops::Add<&'a Self, Output=Self> +
    for<'a> std::ops::AddAssign<&'a Self>
{
    fn zero() -> Self;
}
pub trait WithOne: Sized +
    for<'a> std::ops::Mul<&'a Self, Output=Self> +
    for<'a> std::ops::MulAssign<&'a Self>
{
    fn one() -> Self;
}
pub trait Integer: Eq + Ord + WithZero + WithOne +
    for<'a> std::ops::Sub<&'a Self, Output=Self> +
    for<'a> std::ops::SubAssign<&'a Self> +
    for<'a> std::ops::Div<&'a Self, Output=Self> +
    for<'a> std::ops::DivAssign<&'a Self> +
    for<'a> std::ops::Rem<&'a Self, Output=Self> +
    for<'a> std::ops::RemAssign<&'a Self>
{}
pub trait ToSigned {
    type Signed: Integer;
    fn to_signed(&self) -> Option<Self::Signed>;
    unsafe fn to_signed_unchecked(&self) -> Self::Signed {
        self.to_signed().unwrap()
    }
}
pub trait ToUnsigned {
    type Unsigned: Integer;
    fn to_unsigned(&self) -> Option<Self::Unsigned>;
    unsafe fn to_unsigned_unchecked(&self) -> Self::Unsigned {
        self.to_unsigned().unwrap()
    }
}

// SNIPPET int
pub trait PrimitiveInteger: Integer + Copy + ToSigned + ToUnsigned {
    fn abs_diff(self, rhs: Self) -> Self;
}
macro_rules! impl_primitive_integer_unsigned {
    ( $($t: ty, $t_signed: ty);* ) => { $(
        impl WithZero for $t {
            fn zero() -> $t { 0 }
        }
        impl WithOne for $t {
            fn one() -> $t { 1 }
        }
        impl Integer for $t {}
        impl ToSigned for $t {
            type Signed = $t_signed;
            fn to_signed(&self) -> Option<$t_signed> {
                use std::convert::TryInto;
                (*self).try_into().ok()
            }
            unsafe fn to_signed_unchecked(&self) -> $t_signed {
                *self as $t_signed
            }
        }
        impl ToUnsigned for $t {
            type Unsigned = $t;
            fn to_unsigned(&self) -> Option<$t> {
                Some(*self)
            }
        }
        impl PrimitiveInteger for $t {
            fn abs_diff(self, rhs: $t) -> $t {
                if self < rhs { rhs - self } else { self - rhs }
            }
        }
    )* }
}
impl_primitive_integer_unsigned!(
    u8, i8;
    u16, i16;
    u32, i32;
    u64, i64;
    u128, i128;
    usize, isize
);
macro_rules! impl_primitive_integer_signed {
    ( $($t: ty, $t_unsigned: ty);* ) => { $(
        impl WithZero for $t {
            fn zero() -> $t { 0 }
        }
        impl WithOne for $t {
            fn one() -> $t { 1 }
        }
        impl Integer for $t {}
        impl ToSigned for $t {
            type Signed = $t;
            fn to_signed(&self) -> Option<$t> {
                Some(*self)
            }
        }
        impl ToUnsigned for $t {
            type Unsigned = $t_unsigned;
            fn to_unsigned(&self) -> Option<$t_unsigned> {
                use std::convert::TryInto;
                (*self).try_into().ok()
            }
            unsafe fn to_unsigned_unchecked(&self) -> $t_unsigned {
                *self as $t_unsigned
            }
        }
        impl PrimitiveInteger for $t {
            fn abs_diff(self, rhs: $t) -> $t {
                if self < rhs { rhs - self } else { self - rhs }
            }
        }
    )* }
}
impl_primitive_integer_signed!(
    i8, u8;
    i16, u16;
    i32, u32;
    i64, u64;
    i128, u128;
    isize, usize
);
pub trait PrimitiveUnsigned: PrimitiveInteger {
    fn checked_mul(self, rhs: Self) -> Option<Self>;
    fn ceil_div(self, rhs: Self) -> Self;
    fn round_div(self, rhs: Self) -> Self;
    fn log2(self) -> Option<Self>;
    fn ceil_log2(self) -> Option<Self>;
    fn sqrt(self) -> Self;
    fn gcd(self, other: Self) -> Self {
        if other == Self::zero() { self } else { other.gcd(self % &other) }
    }
    fn lcm(self, other: Self) -> Self {
        if self == Self::zero() || other == Self::zero() { Self::zero() } else {
            let gcd = self.gcd(other);
            self / &gcd * &other
        }
    }
    fn divisors(self) -> Option<Divisors<Self>> {
        (self != Self::zero()).then_with(|| Divisors {
            num: self,
            current: Some(Self::one()),
            latter: Vec::new()
        })
    }
    fn factorize<Exp: PrimitiveUnsigned>(self) -> Option<Factorize<Self, Exp>> {
        (self != Self::zero()).then_with(|| Factorize {
            rest: self,
            current: Self::one() + &Self::one(),
            phantom: std::marker::PhantomData
        })
    }
    fn prime_factors(self) -> Option<PrimeFactors<Self>> {
        (self != Self::zero()).then_with(|| PrimeFactors {
            rest: self,
            current: Self::one() + &Self::one()
        })
    }
}
pub struct Divisors<T> {
    num: T,
    current: Option<T>,
    latter: Vec<T>
}
impl<T: PrimitiveUnsigned> Iterator for Divisors<T> {
    type Item = T;
    fn next(&mut self) -> Option<T> {
        match self.current {
            None => self.latter.pop(),
            Some(mut cur) => {
                loop {
                    if cur.checked_mul(cur).map_or(true, |square| square > self.num) {
                        self.current = None;
                        return self.latter.pop();
                    }
                    if self.num % &cur == T::zero() {
                        break;
                    }
                    cur += &T::one();
                }
                self.current = Some(cur + &T::one());
                if cur * &cur != self.num {
                    self.latter.push(self.num / &cur);
                }
                Some(cur)
            }
        }
    }
}
pub struct Factorize<T, Exp> {
    rest: T,
    current: T,
    phantom: std::marker::PhantomData<Exp>
}
impl<T: PrimitiveUnsigned, Exp: PrimitiveUnsigned> Iterator for Factorize<T, Exp> {
    type Item = (T, Exp);
    fn next(&mut self) -> Option<(T, Exp)> {
        if self.rest == T::one() {
            return None;
        }
        loop {
            if self.current.checked_mul(self.current).map_or(true, |square| square > self.rest) {
                let factor = self.rest;
                self.rest = T::one();
                return Some((factor, Exp::one()));
            }
            let mut exp = Exp::zero();
            while self.rest % &self.current == T::zero() {
                exp += &Exp::one();
                self.rest /= &self.current;
            }
            self.current += &T::one();
            if exp > Exp::zero() {
                let cur = self.current - &T::one();
                return Some((cur, exp));
            }
        }
    }
}
pub struct PrimeFactors<T> {
    rest: T,
    current: T
}
impl<T: PrimitiveUnsigned> Iterator for PrimeFactors<T> {
    type Item = T;
    fn next(&mut self) -> Option<T> {
        if self.rest == T::one() {
            return None;
        }
        loop {
            if self.current.checked_mul(self.current).map_or(true, |square| square > self.rest) {
                let factor = self.rest;
                self.rest = T::one();
                return Some(factor);
            }
            let mut divisible = false;
            while self.rest % &self.current == T::zero() {
                divisible = true;
                self.rest /= &self.current;
            }
            self.current += &T::one();
            if divisible {
                return Some(self.current - &T::one());
            }
        }
    }
}
macro_rules! impl_primitive_unsigned {
    ( $($t: ty)* ) => { $(
        impl PrimitiveUnsigned for $t {
            fn checked_mul(self, rhs: $t) -> Option<$t> {
                self.checked_mul(rhs)
            }
            fn ceil_div(self, rhs: $t) -> $t {
                (self + rhs - 1) / rhs
            }
            fn round_div(self, rhs: $t) -> $t {
                (self + rhs/2) / rhs
            }
            fn log2(mut self) -> Option<$t> {
                if self == 0 {
                    None
                } else {
                    let mut ans = 0;
                    while self > 1 {
                        ans += 1;
                        self /= 2;
                    }
                    Some(ans)
                }
            }
            fn ceil_log2(self) -> Option<$t> {
                self.log2().map(|x| {
                    (self + ((1<<x) - 1)).log2().unwrap()
                })
            }
            fn sqrt(self) -> $t {
                (self as f64).sqrt() as $t
            }
        }
    )* }
}
impl_primitive_unsigned!(u8 u16 u32 u64 u128 usize);
pub trait PrimitiveSigned: PrimitiveInteger {
    fn bezout(self, other: Self) -> (Self, Self, Self::Unsigned);
}
unsafe fn bezout_sub<T: PrimitiveUnsigned>(a: T, b: T) -> (T::Signed, T::Signed, T) {
    if b == T::zero() { (T::Signed::one(), T::Signed::zero(), a) } else {
        let m = (a / &b).to_signed_unchecked();
        let (x, y, g) = bezout_sub(b, a % &b);
        let solution_b = x - &(m * &y);
        (y, solution_b, g)
    }
}
macro_rules! impl_primitive_signed {
    ( $($t: ty)* ) => { $(
        impl PrimitiveSigned for $t {
            fn bezout(self, other: $t) -> ($t, $t, <$t as ToUnsigned>::Unsigned) {
                let (x, y, g) = unsafe { bezout_sub(
                    (self * self.signum()).to_unsigned_unchecked(),
                    (other * other.signum()).to_unsigned_unchecked()
                ) };
                (x * self.signum(), y * other.signum(), g)
            }
        }
    )* }
}
impl_primitive_signed!(i8 i16 i32 i64 i128 isize);

// SNIPPET iter
pub struct Chunks<I> {
    iter: I,
    size: usize
}
impl<I: Iterator> Iterator for Chunks<I> {
    type Item = Vec<I::Item>;
    fn next(&mut self) -> Option<Self::Item> {
        let first = self.iter.next();
        if first.is_none() {
            return None;
        }
        let mut chunk = Vec::with_capacity(self.size);
        chunk.push(first.unwrap());
        for _ in 0..self.size-1 {
            match self.iter.next() {
                Some(x) => chunk.push(x),
                None => break
            }
        }
        Some(chunk)
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (lower, upper) = self.iter.size_hint();
        (lower.ceil_div(self.size), upper.map(|u| u.ceil_div(self.size)))
    }
    fn count(self) -> usize {
        self.iter.count().ceil_div(self.size)
    }
    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        if n > 0 {
            self.iter.nth(n * self.size - 1);
        }
        self.next()
    }
}
impl<I: ExactSizeIterator> ExactSizeIterator for Chunks<I> {}
impl<I: std::iter::FusedIterator> std::iter::FusedIterator for Chunks<I> {}
#[derive(Clone)]
pub struct LScan<I, S, F> {
    iter: I,
    state: Option<S>,
    f: F,
}
impl<I: Iterator, S, F> Iterator for LScan<I, S, F>
where
    F: FnMut(&S, I::Item) -> S
{
    type Item = S;
    fn next(&mut self) -> Option<S> {
        if self.state.is_none() {
            return None;
        }
        let state_inner = self.state.take().unwrap();
        if let Some(item) = self.iter.next() {
            self.state = Some((self.f)(&state_inner, item));
        }
        Some(state_inner)
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (lower, upper) = self.iter.size_hint();
        (lower + 1, upper.map(|u| u + 1))
    }
    fn count(self) -> usize {
        self.iter.count() + 1
    }
}
impl<I: ExactSizeIterator, S, F: FnMut(&S, I::Item) -> S> ExactSizeIterator for LScan<I, S, F> {}
impl<I: std::iter::FusedIterator, S, F: FnMut(&S, I::Item) -> S> std::iter::FusedIterator for LScan<I, S, F> {}
pub struct GroupBy<K, I: Iterator, F> {
    cur: Option<(I::Item, K)>,
    iter: I,
    key_fn: F
}
impl<K: Eq, I: Iterator, F: FnMut(&I::Item) -> K> Iterator for GroupBy<K, I, F> {
    type Item = (K, Vec<I::Item>);
    fn next(&mut self) -> Option<(K, Vec<I::Item>)> {
        let cur = self.cur.take();
        cur.map(|(item, key)| {
            let mut group = vec![item];
            loop {
                let next = self.iter.next();
                match next {
                    Some(next_item) => {
                        let next_key = (self.key_fn)(&next_item);
                        if key == next_key {
                            group.push(next_item);
                        } else {
                            self.cur = Some((next_item, next_key));
                            break;
                        }
                    }
                    None => {
                        self.cur = None;
                        break;
                    }
                }
            }
            (key, group)
        })
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.cur.is_none() {
            (0, Some(0))
        } else {
            let (_, upper) = self.iter.size_hint();
            (1, upper.map(|u| u + 1))
        }
    }
}
impl<K: Eq, I: Iterator, F: FnMut(&I::Item) -> K> std::iter::FusedIterator for GroupBy<K, I, F> {}
pub struct RunLength<I: Iterator> {
    cur: Option<I::Item>,
    iter: I
}
impl<I: Iterator> Iterator for RunLength<I> where I::Item: Eq {
    type Item = (I::Item, usize);
    fn next(&mut self) -> Option<(I::Item, usize)> {
        let cur = self.cur.take();
        cur.map(|value| {
            let mut length = 1;
            loop {
                let next = self.iter.next();
                match next {
                    Some(next_value) => {
                        if value == next_value {
                            length += 1;
                        } else {
                            self.cur = Some(next_value);
                            break;
                        }
                    }
                    None => {
                        self.cur = None;
                        break;
                    }
                }
            }
            (value, length)
        })
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.cur.is_none() {
            (0, Some(0))
        } else {
            let (_, upper) = self.iter.size_hint();
            (1, upper.map(|u| u + 1))
        }
    }
}
impl<I: Iterator> std::iter::FusedIterator for RunLength<I> where I::Item: Eq {}
pub trait IteratorExt: Iterator {
    fn chunks(self, size: usize) -> Chunks<Self> where Self: Sized {
        assert!(size > 0);
        Chunks {
            iter: self,
            size: size
        }
    }
    fn lscan<S, F>(self, state: S, f: F) -> LScan<Self, S, F>
    where
        Self: Sized,
        F: FnMut(&S, Self::Item) -> S,
    {
        LScan {
            iter: self,
            state: Some(state),
            f: f,
        }
    }
    fn lscan1<F>(mut self, f: F) -> Option<LScan<Self, Self::Item, F>>
    where
        Self: Sized,
        Self::Item: Clone,
        F: FnMut(&Self::Item, Self::Item) -> Self::Item
    {
        self.next().map(|first| self.lscan(first, f))
    }
    fn get_unique(mut self) -> Option<Self::Item> where Self: Sized, Self::Item: Eq {
        let first_opt = self.next();
        first_opt.and_then(|first| {
            if self.all(|item| item == first) { Some(first) } else { None }
        })
    }
    fn group_by<K: Eq, F: FnMut(&Self::Item) -> K>(mut self, mut f: F) -> GroupBy<K, Self, F> where Self: Sized {
        let next = self.next();
        GroupBy {
            cur: next.map(|item| {
                let key = f(&item);
                (item, key)
            }),
            iter: self,
            key_fn: f
        }
    }
    fn run_length(mut self) -> RunLength<Self> where Self: Sized, Self::Item: Eq {
        RunLength {
            cur: self.next(),
            iter: self
        }
    }
    fn join<T: std::fmt::Display>(mut self, sep: T) -> String
    where
        Self: Sized, Self::Item: std::fmt::Display
    {
        let mut result = String::new();
        if let Some(first) = self.next() {
            result.push_str(&format!("{}", first));
        }
        for s in self {
            result.push_str(&format!("{}{}", sep, s));
        }
        result
    }
    fn cat(self) -> String where Self: Sized, Self::Item: std::fmt::Display { self.join("") }
}
impl<I: Iterator> IteratorExt for I {}
pub trait IteratorInnerProduct<T, Rhs=T>: ExactSizeIterator<Item=T> {
    fn inner_product<I, J>(self, other: I) -> Option<<T as std::ops::Mul<Rhs>>::Output>
    where
        Self: Sized,
        I: IntoIterator<Item=Rhs, IntoIter=J>,
        J: Iterator<Item=Rhs> + ExactSizeIterator,
        T: std::ops::Mul<Rhs>,
        <T as std::ops::Mul<Rhs>>::Output: std::iter::Sum
    {
        let iter = other.into_iter();
        (self.len() == iter.len()).then_with(|| {
            self.zip(iter).map(|(a, b)| a * b).sum()
        })
    }
}
impl<T1, T2, I> IteratorInnerProduct<T1, T2> for I
where
    I: Iterator<Item=T1> + ExactSizeIterator,
    T1: std::ops::Mul<T2>
{}
pub struct Unfold<State, T, F> where F: FnMut(&State) -> Option<(T, State)> {
    state: State,
    f: F
}
impl<State, T, F> Iterator for Unfold<State, T, F> where F: FnMut(&State) -> Option<(T, State)> {
    type Item = T;
    fn next(&mut self) -> Option<T> {
        (self.f)(&self.state).map(|(value, state)| {
            self.state = state;
            value
        })
    }
}
pub fn unfold<State, T, F>(init: State, f: F) -> Unfold<State, T, F> where F: FnMut(&State) -> Option<(T, State)> {
    Unfold { state: init, f: f }
}
pub struct Iterate<T, F> where F: FnMut(&T) -> T {
    state: T,
    f: F
}
impl<T, F> Iterator for Iterate<T, F> where F: FnMut(&T) -> T {
    type Item = T;
    fn next(&mut self) -> Option<T> {
        use std::mem::swap;
        let mut state = (self.f)(&self.state);
        swap(&mut state, &mut self.state);
        Some(state)
    }
}
pub fn iterate<T, F>(init: T, f: F) -> Iterate<T, F>
where
    F: FnMut(&T) -> T
{
    Iterate { state: init, f: f }
}
pub struct IterateMap<State, T, F> where F: FnMut(&State) -> (T, State) {
    state: State,
    f: F
}
impl<State, T, F> Iterator for IterateMap<State, T, F> where F: FnMut(&State) -> (T, State) {
    type Item = T;
    fn next(&mut self) -> Option<T> {
        let (value, state) = (self.f)(&self.state);
        self.state = state;
        Some(value)
    }
}
pub fn iterate_map<State, T, F>(init: State, f: F) -> IterateMap<State, T, F>
where
    F: FnMut(&State) -> (T, State)
{
    IterateMap { state: init, f }
}

// SNIPPET range
pub trait UsizeRangeBoundsExt {
    fn to_range(&self, len: usize) -> Option<std::ops::Range<usize>>;
}
impl<T: std::ops::RangeBounds<usize>> UsizeRangeBoundsExt for T {
    #[allow(unstable_name_collisions)]
    fn to_range(&self, len: usize) -> Option<std::ops::Range<usize>> {
        use std::ops::Bound::*;
        let start = match self.start_bound() {
            Included(&i) => i,
            Excluded(&i) => i+1,
            Unbounded => 0
        };
        let end = match self.end_bound() {
            Included(&i) => i+1,
            Excluded(&i) => i,
            Unbounded => len,
        };
        (start <= end && end <= len).then(start..end)
    }
}
pub trait BoundCloned<T> {
    fn cloned(self) -> std::ops::Bound<T>;
}
impl<T: Clone> BoundCloned<T> for std::ops::Bound<&T> {
    fn cloned(self) -> std::ops::Bound<T> {
        match self {
            std::ops::Bound::Included(x) => std::ops::Bound::Included(x.clone()),
            std::ops::Bound::Excluded(x) => std::ops::Bound::Excluded(x.clone()),
            std::ops::Bound::Unbounded => std::ops::Bound::Unbounded
        }
    }
}
pub trait BoundExt<T> {
    fn map<U>(self, f: impl FnOnce(T) -> U) -> std::ops::Bound<U>;
}
impl<T> BoundExt<T> for std::ops::Bound<T> {
    fn map<U>(self, f: impl FnOnce(T) -> U) -> std::ops::Bound<U> {
        match self {
            std::ops::Bound::Included(x) => std::ops::Bound::Included(f(x)),
            std::ops::Bound::Excluded(x) => std::ops::Bound::Excluded(f(x)),
            std::ops::Bound::Unbounded => std::ops::Bound::Unbounded
        }
    }
}

// SNIPPET cmp
use std::cmp::{Ord, Ordering};
pub fn minmax<T: Ord>(a: T, b: T) -> (T, T) {
    if a <= b { (a, b) } else { (b, a) }
}
#[macro_export]
macro_rules! chmin {
    ($place: expr, $expr: expr) => {
        let value = $expr;
        if value < $place {
            $place = value;
        }
    }
}
#[macro_export]
macro_rules! chmax {
    ($place: expr, $expr: expr) => {
        let value = $expr;
        if value > $place {
            $place = value;
        }
    }
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default, Hash)]
pub struct Reverse<T: Ord>(pub T);
impl<T: Ord> PartialOrd for Reverse<T> {
    fn partial_cmp(&self, other: &Reverse<T>) -> Option<Ordering> {
        other.0.partial_cmp(&self.0)
    }
}
impl<T: Ord> Ord for Reverse<T> {
    fn cmp(&self, other: &Reverse<T>) -> Ordering {
        other.0.cmp(&self.0)
    }
}
pub trait SortDesc<T> {
    fn sort_desc(&mut self) where T: Ord;
    fn sort_desc_by<F>(&mut self, cmp: F)
    where
        F: FnMut(&T, &T) -> std::cmp::Ordering;
    fn sort_desc_by_key<K: Ord, F: FnMut(&T) -> K>(&mut self, key: F);
    fn sort_unstable_desc(&mut self) where T: Ord;
    fn sort_unstable_desc_by<F>(&mut self, cmp: F)
    where
        F: FnMut(&T, &T) -> std::cmp::Ordering;
    fn sort_unstable_desc_by_key<K: Ord, F: FnMut(&T) -> K>(&mut self, key: F);
}
impl<T> SortDesc<T> for [T] {
    fn sort_desc(&mut self) where T: Ord {
        self.sort_by(|x, y| y.cmp(x));
    }
    fn sort_desc_by<F>(&mut self, mut cmp: F)
    where
        F: FnMut(&T, &T) -> std::cmp::Ordering
    {
        self.sort_by(|x, y| cmp(y, x));
    }
    fn sort_desc_by_key<K: Ord, F: FnMut(&T) -> K>(&mut self, mut key: F) {
        self.sort_by_key(|x| Reverse(key(x)));
    }
    fn sort_unstable_desc(&mut self) where T: Ord {
        self.sort_unstable_by(|x, y| y.cmp(x));
    }
    fn sort_unstable_desc_by<F>(&mut self, mut cmp: F)
    where
        F: FnMut(&T, &T) -> std::cmp::Ordering
    {
        self.sort_unstable_by(|x, y| cmp(y, x));
    }
    fn sort_unstable_desc_by_key<K: Ord, F: FnMut(&T) -> K>(&mut self, mut key: F) {
        self.sort_unstable_by_key(|x| Reverse(key(x)));
    }
}
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug, Default, Hash)]
pub struct Total<T: PartialOrd + PartialEq>(pub T);
impl<T: PartialOrd + PartialEq> Eq for Total<T> {}
impl<T: PartialOrd + PartialEq> Ord for Total<T> {
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}
pub trait IteratorMinmax: Iterator {
    fn minmax(self) -> Option<(Self::Item, Self::Item)>;
    fn minmax_by_key<K, F>(self, key_fn: F) -> Option<(Self::Item, Self::Item)>
    where
        K: Ord,
        F: FnMut(&Self::Item) -> K;
    fn minmax_by<F>(self, compare: F) -> Option<(Self::Item, Self::Item)>
    where
        F: FnMut(&Self::Item, &Self::Item) -> Ordering;
}
impl<T: Ord + Clone, I: Iterator<Item=T>> IteratorMinmax for I {
    fn minmax(self) -> Option<(Self::Item, Self::Item)> {
        self.minmax_by(|a, b| a.cmp(b))
    }
    fn minmax_by_key<K, F>(self, mut key_fn: F) -> Option<(Self::Item, Self::Item)>
    where
        K: Ord,
        F: FnMut(&Self::Item) -> K
    {
        self.minmax_by(|a, b| key_fn(a).cmp(&key_fn(b)))
    }
    fn minmax_by<F>(mut self, mut compare: F) -> Option<(Self::Item, Self::Item)>
    where
        F: FnMut(&Self::Item, &Self::Item) -> Ordering
    {
        let first = self.next()?;
        let second = match self.next() {
            Some(x) => x,
            None => return Some((first.clone(), first))
        };
        let mut result = minmax(first, second);
        while let Some(x) = self.next() {
            let (min, max) = result;
            result = if compare(&x, &min) == Ordering::Less {
                (x, max)
            } else if compare(&max, &x) == Ordering::Less {
                (min, x)
            } else {
                (min, max)
            };
        }
        Some(result)
    }
}
pub trait WithCmpIdentity<T>: Sized {
    fn new(x: T) -> Self;
    fn inf() -> Self;
    fn as_option(&self) -> Option<&T>;
    fn as_option_mut(&mut self) -> Option<&mut T>;
    fn into_option(self) -> Option<T>;
    fn is_fin(&self) -> bool {
        self.as_option().is_some()
    }
    fn is_inf(&self) -> bool {
        self.as_option().is_none()
    }
    fn expect_fin(self, msg: &str) -> T {
        self.into_option().expect(msg)
    }
    fn fin(self) -> T {
        self.into_option().unwrap()
    }
    fn fin_or(self, default: T) -> T {
        self.into_option().unwrap_or(default)
    }
    fn fin_or_else<F: FnOnce() -> T>(self, f: F) -> T {
        self.into_option().unwrap_or_else(f)
    }
    fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U {
        self.into_option().map_or(default, f)
    }
    fn map_or_else<U, D, F>(self, default: D, f: F) -> U
    where
        D: FnOnce() -> U,
        F: FnOnce(T) -> U
    {
        self.into_option().map_or_else(default, f).into()
    }
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum MaybeNegInf<T> {
    Inf,
    Fin(T)
}
pub type Max<T> = MaybeNegInf<T>;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum MaybeInf<T> {
    Fin(T),
    Inf
}
pub type Min<T> = MaybeInf<T>;
macro_rules! impl_with_cmp_identity {
    ($t:ident) => {
        impl<T> $t<T> {
            pub fn map<U: Ord, F: FnOnce(T) -> U>(self, f: F) -> $t<U> {
                match self {
                    $t::Fin(x) => $t::Fin(f(x)),
                    $t::Inf => $t::Inf
                }
            }
        }
        impl<T> WithCmpIdentity<T> for $t<T> {
            fn new(x: T) -> $t<T> { $t::Fin(x) }
            fn inf() -> $t<T> { $t::Inf }
            fn as_option(&self) -> Option<&T> {
                match self {
                    $t::Fin(x) => Some(x),
                    $t::Inf => None
                }
            }
            fn as_option_mut(&mut self) -> Option<&mut T> {
                match self {
                    $t::Fin(x) => Some(x),
                    $t::Inf => None
                }
            }
            fn into_option(self) -> Option<T> {
                match self {
                    $t::Fin(x) => Some(x),
                    $t::Inf => None
                }
            }
        }
    }
}
impl_with_cmp_identity!(MaybeNegInf);
impl_with_cmp_identity!(MaybeInf);

// END SNIPPETS
// Here is the documentation: https://yoshrc.github.io/rust-atcoder-snippets/atcoder_snippets/index.html

use std::cmp;

fn main() {
    read!(r = usize, c = usize, !);
    let mut items_on_row = vec![vec![]; r];
    for (r, c, v) in read_lines::<(usize_, usize_, i64)>() {
        items_on_row[r].push((c, v));
    }
    for is in &mut items_on_row {
        is.push((c, 0));
        is.sort();
    }

    let mut prev: [Vec<i64>; 4] = [vec![0; c+1], vec![0; c+1], vec![0; c+1], vec![0; c+1]];
    for y in 0..r {
        let mut next = [vec![0; c+1], vec![0; c+1], vec![0; c+1], vec![0; c+1]];

        for picked in 0..=3 {
            let mut item_i = 0;
            for x in 0..c {
                if picked == 0 {
                    next[0][x+1] = cmp::max(prev[3][x+1], next[0][x]);
                    continue;
                }

                next[picked][x+1] = next[picked-1][x+1];
                chmax!(next[picked][x+1], cmp::max(prev[3][x+1], next[picked][x]));
                let (item_x, item_v) = items_on_row[y][item_i];
                if item_x == x {
                    dbg!((y, x, picked, next[picked-1][x+1]));
                    chmax!(next[picked][x+1], item_v + prev[3][x+1]);
                    chmax!(next[picked][x+1], item_v + next[picked-1][x]);
                    item_i += 1;
                }
            }
        }
        prev = next;
        dbg!(&prev);
    }
    echo!(prev[3].last().unwrap());
}