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: Time Limit Exceeded)

#![allow(unused_imports)]

pub mod pcl {
pub mod math{use num::{Num,One,Zero};use std::cmp::Ordering;use std::fmt;use std::hash::{Hash,Hasher};use std::iter::{Product,Sum};use std::marker::PhantomData;use std::mem;use std::ops::{Add,AddAssign,Div,DivAssign,Mul,MulAssign,Rem,RemAssign,Sub,SubAssign,};pub type ModintInnerType=i64;pub trait ModintConst{const MOD:ModintInnerType;}#[macro_export] macro_rules!define_modint_const{(pub const $name:ident=$value:literal;)=>{pub enum $name{}impl crate::pcl::math::ModintConst for $name{const MOD:crate::pcl::math::ModintInnerType=$value;}};}define_modint_const!{pub const MOD17=1_000_000_007;}pub type Modint17=Modint<MOD17>;pub struct Modint<C>{value:ModintInnerType,marker:PhantomData<C>,}impl<C>Modint<C>{pub unsafe fn new_unchecked(value:ModintInnerType)->Modint<C>{Modint{value,marker:PhantomData,}}pub fn inner(self)->ModintInnerType{self.value}}impl<C:ModintConst>Modint<C>{pub fn new(mut value:ModintInnerType)->Modint<C>{assert_ne!(C::MOD,0,"MOD is 0");if value<0{let m=(-value)/C::MOD;value+=(m+1)*C::MOD;}unsafe{Modint::new_unchecked(value%C::MOD)}}pub fn inv(self)->Modint<C>{let mut a=self.value;let mut modulo=C::MOD;let mut u=1;let mut v=0;while modulo>0{let t=a/modulo;a-=t*modulo;u-=t*v;mem::swap(&mut a,&mut modulo);mem::swap(&mut u,&mut v);}Modint::new(u)}}impl<C:ModintConst>PartialEq for Modint<C>{fn eq(&self,other:&Self)->bool{self.inner()==other.inner()}}impl<C:ModintConst>PartialOrd for Modint<C>{fn partial_cmp(&self,other:&Self)->Option<Ordering>{self.inner().partial_cmp(&other.inner())}}impl<C:ModintConst>Eq for Modint<C>{}impl<C:ModintConst>Ord for Modint<C>{fn cmp(&self,other:&Self)->Ordering{self.inner().cmp(&other.inner())}}impl<C:ModintConst>Hash for Modint<C>{fn hash<H:Hasher>(&self,state:&mut H){self.inner().hash(state);}}impl<C>fmt::Debug for Modint<C>{fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{write!(f,"{}",self.inner())}}impl<C>Clone for Modint<C>{fn clone(&self)->Self{*self}}impl<C>Copy for Modint<C>{}impl<C:ModintConst>AddAssign for Modint<C>{fn add_assign(&mut self,rhs:Modint<C>){self.value+=rhs.value;if self.value>=C::MOD{self.value-=C::MOD;}}}impl<C:ModintConst>SubAssign for Modint<C>{fn sub_assign(&mut self,rhs:Modint<C>){self.value-=rhs.value;if self.value<0{self.value+=C::MOD;}}}impl<C:ModintConst>MulAssign for Modint<C>{fn mul_assign(&mut self,rhs:Modint<C>){self.value*=rhs.value;self.value%=C::MOD;}}impl<C:ModintConst>DivAssign for Modint<C>{fn div_assign(&mut self,rhs:Modint<C>){if rhs.value==0{panic!("attempted to divide by zero");}*self*=rhs.inv();}}impl<C:ModintConst>RemAssign for Modint<C>{fn rem_assign(&mut self,rhs:Modint<C>){if rhs.value==0{panic!("attempted to divide by zero.")}self.value%=rhs.value;}}macro_rules!impl_arith_by_assign{(impl $trait:ident::$fnname:ident{use $op:tt;})=>{impl<C:ModintConst>$trait for Modint<C>{type Output=Modint<C>;fn $fnname(mut self,rhs:Modint<C>)->Modint<C>{self $op rhs;self}}};}impl_arith_by_assign!(impl Add::add{use+=;});impl_arith_by_assign!(impl Sub::sub{use-=;});impl_arith_by_assign!(impl Mul::mul{use*=;});impl_arith_by_assign!(impl Div::div{use/=;});impl_arith_by_assign!(impl Rem::rem{use%=;});impl<C:ModintConst>One for Modint<C>{fn one()->Modint<C>{assert_ne!(C::MOD,1,"one()is called for Modint with MOD=1");unsafe{Modint::new_unchecked(1)}}}impl<C:ModintConst>Sum for Modint<C>{fn sum<I:Iterator<Item=Modint<C>>>(iter:I)->Modint<C>{iter.fold(Modint::zero(),Add::add)}}impl<C:ModintConst>Product for Modint<C>{fn product<I:Iterator<Item=Modint<C>>>(iter:I)->Self{iter.fold(Modint::one(),Mul::mul)}}impl<C:ModintConst>Zero for Modint<C>{fn zero()->Modint<C>{unsafe{Modint::new_unchecked(0)}}fn is_zero(&self)->bool{self.inner()==0}}impl<C>fmt::Display for Modint<C>{fn fmt(&self,b:&mut fmt::Formatter)->fmt::Result{write!(b,"{}",self.inner())}}impl<C:ModintConst>Num for Modint<C>{type FromStrRadixErr=<ModintInnerType as Num>::FromStrRadixErr;fn from_str_radix(src:&str,radix:u32)->Result<Self,Self::FromStrRadixErr>{ModintInnerType::from_str_radix(src,radix).map(Modint::new)}}}pub mod sum{use crate::pcl::traits::Group;use std::cmp;use std::ops::{Bound,RangeBounds};pub struct CumSum<T>{sum:Vec<T>,}impl<T:Group+Copy>CumSum<T>{pub fn from_array<A:AsRef<[T]>>(array:A)->CumSum<T>{let array=array.as_ref();let mut sum=vec![T::zero();array.len()+1];for i in 1..=array.len(){unsafe{*sum.get_unchecked_mut(i)=*sum.get_unchecked(i-1)+*array.get_unchecked(i-1);}}CumSum{sum}}pub fn sum<R:RangeBounds<usize>>(&self,range:R)->T{let orig_len=self.sum.len()-1;let start=range_start(&range,0);let end=range_end(&range,orig_len);if end<=start{return T::zero();}unsafe{*self.sum.get_unchecked(end)-*self.sum.get_unchecked(start)}}}pub struct CumSum2D<T>{sum:Vec<Vec<T>>,}impl<T:Group+Copy>CumSum2D<T>{pub fn from_matrix<M,A>(matrix:M)->CumSum2D<T>where M:AsRef<[A]>,A:AsRef<[T]>,{let array=matrix.as_ref();let height=array.len();if height==0{return CumSum2D{sum:vec![vec![T::zero()]],};}let width=unsafe{array.get_unchecked(0)}.as_ref().len();let mut sum=vec![vec![T::zero();width+1];height+1];for i in 1..=height{for j in 1..=width{assert_eq!(unsafe{array.get_unchecked(i-1)}.as_ref().len(),width,"the array's length is differ line by line");unsafe{*sum.get_unchecked_mut(i).get_unchecked_mut(j)=*sum.get_unchecked(i-1).get_unchecked(j)+*sum.get_unchecked(i).get_unchecked(j-1)-*sum.get_unchecked(i-1).get_unchecked(j-1)+*array.get_unchecked(i-1).as_ref().get_unchecked(j-1)}}}CumSum2D{sum}}pub fn sum<RY,RX>(&self,yrange:RY,xrange:RX)->T where RY:RangeBounds<usize>,RX:RangeBounds<usize>,{let orig_height=self.sum.len()-1;let orig_width=unsafe{self.sum.get_unchecked(0).len()}-1;let ystart=range_start(&yrange,0);let yend=range_end(&yrange,orig_height);let xstart=range_start(&xrange,0);let xend=range_end(&xrange,orig_width);if yend<=ystart||xend<=xstart{return T::zero();}unsafe{*self.sum.get_unchecked(yend).get_unchecked(xend)+*self.sum.get_unchecked(ystart).get_unchecked(xstart)-*self.sum.get_unchecked(ystart).get_unchecked(xend)-*self.sum.get_unchecked(yend).get_unchecked(xstart)}}}fn range_start<R:RangeBounds<usize>>(range:&R,min:usize)->usize{let start=match range.start_bound(){Bound::Included(&x)=>x,Bound::Excluded(&x)=>x+1,Bound::Unbounded=>0,};cmp::max(start,min)}fn range_end<R:RangeBounds<usize>>(range:&R,max:usize)->usize{let end=match range.end_bound(){Bound::Included(&x)=>x+1,Bound::Excluded(&x)=>x,Bound::Unbounded=>max,};cmp::min(end,max)}}pub mod traits{pub mod math{use num::Zero;use std::ops::{Add,Neg,Sub};pub trait Group:Add<Output=Self>+Sub<Output=Self>+Neg+Zero{}impl<T>Group for T where T:Add<Output=Self>+Sub<Output=Self>+Neg+Zero{}}pub use self::math::*;}
}

use itertools::Itertools as _;
use proconio::input;
use std::cmp::max;
use std::collections::HashMap;
use std::i64;

const INF: i64 = i64::MAX / 2;

fn calc(dp: &mut Vec<HashMap<usize, i64>>, a: &[i64], i: usize, j: usize) -> i64 {
    match (i, j) {
        (_, 0) => return 0,
        (0, _) => return -INF,
        (1, 1) => return a[0],
        (1, _) => return -INF,
        _ => (),
    }

    match dp[i].get(&j) {
        Some(&v) => v,
        None => {
            let res = max(calc(dp, a, i - 1, j), calc(dp, a, i - 2, j - 1) + a[i - 1]);
            dp[i].insert(j, res);
            res
        }
    }
}

fn main() {
    input! {
        n: usize,
        a: [i64; n],
    }

    let mut dp = vec![HashMap::new(); n + 1];

    println!("{}", calc(&mut dp, &a, n, n / 2));
}