Problem:
Score : 600 points

Problem Statement

Given is an integer sequence A_1, ..., A_N of length N.

We will choose exactly \left\lfloor \frac{N}{2} \right\rfloor elements from this sequence so that no two adjacent elements are chosen.

Find the maximum possible sum of the chosen elements.

Here \lfloor x \rfloor denotes the greatest integer not greater than x.

Constraints

2 \leq N \leq 2\times 10^5

|A_i|\leq 10^9

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
A_1 ... A_N

Output

Print the maximum possible sum of the chosen elements.

Sample Input 1

6
1 2 3 4 5 6

Sample Output 1

12

Choosing 2, 4, and 6 makes the sum 12, which is the maximum possible value.

Sample Input 2

5
-1000 -100 -10 0 10

Sample Output 2

0

Choosing -10 and 10 makes the sum 0, which is the maximum possible value.

Sample Input 3

10
1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000

Sample Output 3

5000000000

Watch out for overflow.

Sample Input 4

27
18 -28 18 28 -45 90 -45 23 -53 60 28 -74 -71 35 -26 -62 49 -77 57 24 -70 -93 69 -99 59 57 -49

Sample Output 4

295

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

#![allow(dead_code)]
use crate::misc::arr;
use whiteread::Reader;
fn main() {
    let mut scan = Reader::from_stdin_naive();
    let n = scan.p::<usize>();
    let a = arr(n, || scan.p::<i64>());
    let k = 1 + n % 2;
    let mut dp = vecs ! ( - 1i64 << 60 ; n + 1 ; k + 1 );
    dp[0][0] = 0;
    for i in 0..n {
        for j in 0..=k {
            assign ! ( dp [ i + 1 ] [ j + 1 ] max dp [ i ] [ j ] );
            let mut tmp = dp[i][j];
            if (i + j) % 2 == 0 {
                tmp += a[i];
            }
            assign ! ( dp [ i + 1 ] [ j ] max tmp );
        }
    }
    println!("{}", dp[n][k]);
}
mod macros {
    #[macro_export]
    macro_rules ! for_ { ( $ init : stmt ; $ cond : expr ; $ incr : expr , $ body : block ) => { $ init while $ cond { $ body $ incr ; } } ; }
    #[macro_export]
    macro_rules ! vecs { ( $ init : expr ; $ ( $ dim : expr ) ;* ) => { vecs ! ( $ ( $ dim ) ;* => $ init ) } ; ( $ head : expr ; $ ( $ tail : expr ) ;* => $ init : expr ) => { vec ! [ vecs ! ( $ ( $ tail ) ;* => $ init ) ; $ head ] } ; ( $ head : expr => $ init : expr ) => { vec ! [ $ init ; $ head ] } ; }
    #[macro_export]
    macro_rules! chmax {
        ( $ x : expr , $ y : expr ) => {
            if $x < $y {
                $x = $y;
                true
            } else {
                false
            }
        };
    }
    #[macro_export]
    macro_rules! chmin {
        ( $ x : expr , $ y : expr ) => {
            if $x > $y {
                $x = $y;
                true
            } else {
                false
            }
        };
    }
    #[macro_export]
    macro_rules ! assign { ( $ arr : ident $ ( [ $ a : expr ] ) + = $ right : expr ) => { unsafe { assign ! ( $ arr , $ ( [ $ a ] ) + , = , $ right , default ) ; } } ; ( $ arr : ident $ ( [ $ a : expr ] ) + += $ right : expr ) => { unsafe { assign ! ( $ arr , $ ( [ $ a ] ) + , += , $ right , default ) ; } } ; ( $ arr : ident $ ( [ $ a : expr ] ) + -= $ right : expr ) => { unsafe { assign ! ( $ arr , $ ( [ $ a ] ) + , -= , $ right , default ) ; } } ; ( $ arr : ident $ ( [ $ a : expr ] ) + |= $ right : expr ) => { unsafe { assign ! ( $ arr , $ ( [ $ a ] ) + , |= , $ right , default ) ; } } ; ( $ arr : ident $ ( [ $ a : expr ] ) + &= $ right : expr ) => { unsafe { assign ! ( $ arr , $ ( [ $ a ] ) + , &= , $ right , default ) ; } } ; ( $ arr : ident $ ( [ $ a : expr ] ) + ^= $ right : expr ) => { unsafe { assign ! ( $ arr , $ ( [ $ a ] ) + , ^= , $ right , default ) ; } } ; ( $ arr : ident $ ( [ $ a : expr ] ) + min $ right : expr ) => { unsafe { assign ! ( $ arr , $ ( [ $ a ] ) + , ^= , $ right , min ) ; } } ; ( $ arr : ident $ ( [ $ a : expr ] ) + max $ right : expr ) => { unsafe { assign ! ( $ arr , $ ( [ $ a ] ) + , ^= , $ right , max ) ; } } ; ( $ arr : expr , [ $ head : expr ] , $ op : tt , $ right : expr , default ) => { let head = $ head ; if 0 <= head as i64 && ( head as i64 ) < $ arr . len ( ) as i64 { let tmp = $ right ; *$ arr . get_unchecked_mut ( head as usize ) $ op tmp ; } } ; ( $ arr : expr , [ $ head : expr ] , $ op : tt , $ right : expr , min ) => { let head = $ head ; if 0 <= head as i64 && ( head as i64 ) < $ arr . len ( ) as i64 { let tmp = $ right ; *$ arr . get_unchecked_mut ( head as usize ) = std :: cmp :: min ( *$ arr . get_unchecked ( head as usize ) , tmp ) ; } } ; ( $ arr : expr , [ $ head : expr ] , $ op : tt , $ right : expr , max ) => { let head = $ head ; if 0 <= head as i64 && ( head as i64 ) < $ arr . len ( ) as i64 { let tmp = $ right ; *$ arr . get_unchecked_mut ( head as usize ) = std :: cmp :: max ( *$ arr . get_unchecked ( head as usize ) , tmp ) ; } } ; ( $ arr : expr , [ $ head : expr ] $ ( [ $ a : expr ] ) +, $ op : tt , $ right : expr , $ kind : ident ) => { let head = $ head ; if 0 <= head as i64 && ( head as i64 ) < $ arr . len ( ) as i64 { assign ! ( $ arr . get_unchecked_mut ( head as usize ) , $ ( [ $ a ] ) +, $ op , $ right , $ kind ) ; } } ; }
    #[macro_export]
    macro_rules! unwrap {
        ( $ arg : expr ) => {{
            let tmp = $arg;
            if tmp.is_none() {
                return;
            }
            tmp.unwrap()
        }};
    }
    #[macro_export]
    macro_rules! swap {
        ( $ a : expr , $ b : expr ) => {
            let tmp = $a;
            $a = $b;
            $b = tmp;
        };
    }
}
mod misc {
    use crate::tiny_num_traits::ZeroOne;
    use std::collections::{BTreeSet, HashMap};
    use std::ops::{Add, Div, Mul, Sub};
    pub const CONST_1E9_7: i64 = 1_000_000_007;
    pub fn arr<'a, S, T>(n: usize, mut f: S) -> Vec<T>
    where
        S: FnMut() -> T + 'a,
    {
        (0..n).map(|_| f()).collect::<Vec<T>>()
    }
    pub fn adjacent4(
        y: usize,
        x: usize,
        h: usize,
        w: usize,
    ) -> impl Iterator<Item = (usize, usize)> {
        const DYDX: [(isize, isize); 4] = [(-1, 0), (1, 0), (0, -1), (0, 1)];
        DYDX.iter().filter_map(move |&(dy, dx)| {
            let ny = y as isize + dy;
            let nx = x as isize + dx;
            if nx >= 0 && nx < w as isize && ny >= 0 && ny < h as isize {
                Some((ny as usize, nx as usize))
            } else {
                None
            }
        })
    }
    pub fn adjacent8(
        y: usize,
        x: usize,
        h: usize,
        w: usize,
    ) -> impl Iterator<Item = (usize, usize)> {
        const DYDX: [(isize, isize); 8] = [
            (-1, 0),
            (1, 0),
            (0, -1),
            (0, 1),
            (-1, -1),
            (-1, 1),
            (1, -1),
            (1, 1),
        ];
        DYDX.iter().filter_map(move |&(dy, dx)| {
            let ny = y as isize + dy;
            let nx = x as isize + dx;
            if nx >= 0 && nx < w as isize && ny >= 0 && ny < h as isize {
                Some((ny as usize, nx as usize))
            } else {
                None
            }
        })
    }
    pub fn run_length_encoding<T: Clone + PartialEq>(slice: &[T]) -> Vec<(i64, T)> {
        if slice.len() == 0 {
            return vec![];
        }
        let mut acc = vec![];
        let mut current = slice[0].clone();
        let mut cnt = 1i64;
        for i in 1..slice.len() {
            if current != slice[i] {
                acc.push((cnt, current));
                cnt = 0;
            }
            current = slice[i].clone();
            cnt += 1;
        }
        acc.push((cnt, current));
        acc
    }
    pub fn count<T: Eq + std::hash::Hash + Clone>(
        slice: &[T],
    ) -> std::collections::HashMap<T, usize> {
        let mut hmap = std::collections::HashMap::new();
        for item in slice {
            *hmap.entry(item.clone()).or_insert(0) += 1;
        }
        hmap
    }
    pub fn indices_by_elem<T: Eq + std::hash::Hash + Clone>(
        slice: &[T],
    ) -> std::collections::HashMap<T, Vec<usize>> {
        let mut hmap = std::collections::HashMap::new();
        for i in 0..slice.len() {
            hmap.entry(slice[i].clone()).or_insert(vec![]).push(i);
        }
        hmap
    }
    pub fn combine<S: Clone, T: Clone, U: std::iter::FromIterator<(S, T)>>(
        left: &[S],
        right: &[T],
    ) -> U {
        let mut ret = vec![];
        for i in 0..left.len() {
            for j in 0..right.len() {
                ret.push((left[i].clone(), right[j].clone()));
            }
        }
        ret.into_iter().collect::<U>()
    }
    pub fn uncount<T: Clone + Eq + std::hash::Hash>(
        hmap: &std::collections::HashMap<T, usize>,
    ) -> Vec<T> {
        hmap.iter()
            .map(|(k, v)| vec![k.clone(); *v])
            .flatten()
            .collect()
    }
    pub fn max_with_index<T: Ord>(slice: &[T]) -> (usize, &T) {
        let mut value: Option<&T> = None;
        let mut index = 0;
        for i in 0..slice.len() {
            if let Some(v) = value {
                if v < &slice[i] {
                    index = i;
                    value = Some(&slice[i]);
                }
            } else {
                index = i;
                value = Some(&slice[i]);
            }
        }
        (index, value.expect("not found max value"))
    }
    pub fn min_with_index<T: Ord>(slice: &[T]) -> (usize, &T) {
        let mut value: Option<&T> = None;
        let mut index = 0;
        for i in 0..slice.len() {
            if let Some(v) = value {
                if v > &slice[i] {
                    index = i;
                    value = Some(&slice[i]);
                }
            } else {
                index = i;
                value = Some(&slice[i]);
            }
        }
        (index, value.expect("not found min value"))
    }
    pub fn split<T: PartialEq + Clone>(slice: &[T], sep: T) -> Vec<Vec<T>> {
        slice.iter().fold(vec![vec![]], |mut acc, x| {
            if x == &sep {
                acc.push(vec![]);
                acc
            } else {
                let last = acc.len() - 1;
                acc[last].push(x.clone());
                acc
            }
        })
    }
    pub fn join<T: std::fmt::Display>(slice: &[T], sep: &str) -> String {
        let strings = slice.iter().map(|t| format!("{}", t)).collect::<Vec<_>>();
        strings.join(sep)
    }
    pub fn coord_comp(slice: &[i64]) -> (Vec<i64>, HashMap<i64, usize>) {
        let mut set = BTreeSet::new();
        for &item in slice {
            set.insert(item);
        }
        let mut hmap = HashMap::new();
        for (i, &v) in set.iter().enumerate() {
            hmap.insert(v, i);
        }
        (set.into_iter().collect::<Vec<_>>(), hmap)
    }
    pub fn shakutori(n: usize, k: i64, a: &[i64]) -> usize {
        let mut sum = 0;
        let mut right = 0;
        let mut ret = 0;
        for left in 0..n {
            while right < n && sum <= k {
                sum += a[right];
                right += 1;
            }
            ret += right - left;
            if right == left {
                right += 1;
            } else {
                sum -= a[left];
            }
        }
        ret
    }
    pub fn inverse(a: &[usize], n: usize) -> Vec<usize> {
        let mut inv = vec![0; n];
        for i in 0..a.len() {
            inv[a[i]] = i;
        }
        inv
    }
    pub fn pow(x: i64, y: i64) -> i64 {
        (x as f64).powi(y as i32) as i64
    }
    pub fn ceil_div<T: Copy + ZeroOne + Add<Output = T> + Sub<Output = T> + Div<Output = T>>(
        x: T,
        y: T,
    ) -> T {
        (x + y - T::one()) / y
    }
    pub fn ceil_mod<
        T: Copy + ZeroOne + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>,
    >(
        x: T,
        y: T,
    ) -> T {
        ceil_div(x, y) * y
    }
    pub fn unzip<P: Clone, Q: Clone>(v: &[(P, Q)]) -> (Vec<P>, Vec<Q>) {
        (
            v.iter().map(|t| t.0.clone()).collect(),
            v.iter().map(|t| t.1.clone()).collect(),
        )
    }
    pub fn unzip3<P: Clone, Q: Clone, R: Clone>(v: &[(P, Q, R)]) -> (Vec<P>, Vec<Q>, Vec<R>) {
        (
            v.iter().map(|t| t.0.clone()).collect(),
            v.iter().map(|t| t.1.clone()).collect(),
            v.iter().map(|t| t.2.clone()).collect(),
        )
    }
    pub fn base(c: char, b: char) -> usize {
        c as usize - b as usize
    }
    pub fn base_signed(c: char, b: char) -> i64 {
        c as i64 - b as i64
    }
    pub fn is_palindrome<T: Clone + Eq>(chars: &[T]) -> bool {
        let s = chars.to_vec();
        let mut t = s.clone();
        t.reverse();
        (0..s.len()).filter(|&i| s[i] == t[i]).count() == s.len()
    }
}
mod tiny_num_traits {
    pub trait ZeroOne {
        fn zero() -> Self;
        fn one() -> Self;
    }
    macro_rules! impl_zero_one {
        ( $ tpe : ident ) => {
            impl ZeroOne for $tpe {
                fn zero() -> Self {
                    0
                }
                fn one() -> Self {
                    1
                }
            }
        };
    }
    impl_zero_one!(i64);
    impl_zero_one!(i32);
    impl_zero_one!(usize);
}