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 C# (Mono-mcs 6.8.0.105) (judge verdict: Wrong Answer)

/*******************************************************************************
* Author: Nirushuu
* Date: 2020-04-16
*******************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.IO;
using System.Globalization;
using System.Numerics;

/*******************************************************************************
* IO from Kattio.cs from open.kattis.com/help/csharp                          */
public class NoMoreTokensException : Exception
{
}

public class Tokenizer
{
    string[] tokens = new string[0];
    private int pos;
    StreamReader reader;

    public Tokenizer(Stream inStream)
    {
        var bs = new BufferedStream(inStream);
        reader = new StreamReader(bs);
    }

    public Tokenizer() : this(Console.OpenStandardInput())
    {
        // Nothing more to do
    }

    private string PeekNext()
    {
        if (pos < 0)
            // pos < 0 indicates that there are no more tokens
            return null;
        if (pos < tokens.Length)
        {
            if (tokens[pos].Length == 0)
            {
                ++pos;
                return PeekNext();
            }
            return tokens[pos];
        }
        string line = reader.ReadLine();
        if (line == null)
        {
            // There is no more data to read
            pos = -1;
            return null;
        }
        // Split the line that was read on white space characters
        tokens = line.Split(null);
        pos = 0;
        return PeekNext();
    }

    public bool HasNext()
    {
        return (PeekNext() != null);
    }

    public string Next()
    {
        string next = PeekNext();
        if (next == null)
            throw new NoMoreTokensException();
        ++pos;
        return next;
    }
}

public class Scanner : Tokenizer
{

    public int NextInt()
    {
        return int.Parse(Next());
    }

    public long NextLong()
    {
        return long.Parse(Next());
    }

    public float NextFloat()
    {
        return float.Parse(Next());
    }

    public double NextDouble()
    {
        return double.Parse(Next());
    }
}

public class BufferedStdoutWriter : StreamWriter
{
    public BufferedStdoutWriter() : base(new BufferedStream(Console.OpenStandardOutput()))
    {
    }
}
/******************************************************************************/

/*******************************************************************************
* DisjointSet datastructure                                                   */
public struct DisjointSet {
    public int[] parent;
    public int[] rank;
    public DisjointSet(int n) {
        parent = new int[n];
        for (int i = 0; i < n; ++i) {
            parent[i] = i;
        }
        rank = new int[n];
    }

    public int Find(int i) {
        int idx = i;
        var compress = new List<int>();
        while (idx != parent[idx]) {
            compress.Add(idx);
            idx = parent[idx];
        }

        foreach (var e in compress) {   // path compress 
            parent[e] = idx;
        }
        return idx;
    }

    public void Union(int a, int b) {
        int aPar = this.Find(a);
        int bPar = this.Find(b);

        if (rank[aPar] > rank[bPar]) {  // by rank
            parent[bPar] = aPar;
        } else {
            parent[aPar] = bPar;
        }
        if (rank[aPar] == rank[bPar]) {
            ++rank[bPar];
        }
    }
}

class MaxHeap {
    List<int> data;

    public MaxHeap() {
        data = new List<int>();
    }

    public void Push(int a) {
        data.Add(a);
        int idx = data.Count - 1;
        int parent = (int) Math.Floor((double) (idx - 1) / 2);
        while (idx != 0 && (data[idx] > data[parent])) {
            int tmp = data[parent];
            data[parent] = data[idx];
            data[idx] = tmp;

            idx = parent;
            parent = (int) Math.Floor((double) (idx - 1) / 2);
        }
    }

    public int Pop() {
        int res = data[0];
        data[0] = data[data.Count - 1];
        data.RemoveAt(data.Count - 1);

        int idx = 0;
        while (true) {
            int child1 = (2 * idx) + 1;
            int child2 = (2 * idx) + 2;

            if (child1 >= data.Count) { // no children
                break;
            } else if (child2 >= data.Count) {  // one child
                if (data[idx] < data[child1]) {
                    int tmp = data[idx];
                    data[idx] = data[child1];
                    data[child1] = tmp;
                }
                break;
            } else {    // two children
                int maxChild = data[child1] > data[child2] ? child1 : child2;
                if (data[idx] < data[maxChild]) {
                    int tmp = data[idx];
                    data[idx] = data[maxChild];
                    data[maxChild] = tmp;
                    idx = maxChild;
                    continue;
                } else {    // no swap
                    break;
                }
            }
        } 

        return res;           
    }


}


class Dequeue {
    public Dictionary<int, int> data = new Dictionary<int, int>();
    int firstIdx;
    public int Count;
    public Dequeue() {
        data = new Dictionary<int, int>();
        firstIdx = 1;
        Count = 0;
    }

    public void PushFront(int a) {
        data[firstIdx - 1] = a;
        ++Count;
        --firstIdx;
    }

    public void PushBack(int a) {
        data[firstIdx + Count] = a;
        ++Count;
    }

    public int PopFront() {
        --Count;
        ++firstIdx;
        return data[firstIdx - 1];
    }

    public int PopBack() {
        --Count;
        return data[firstIdx + Count];
    }

    public int Get(int n) {
        return data[firstIdx + n];
    }
}
/******************************************************************************/

class MainClass {

    // Debug functions   
    static void debug<T>(IEnumerable<T> a, string s = "") {
        Console.WriteLine($"name: {s}");
        int i = 0;
        foreach (var e in a) {
            Console.WriteLine($"value {i}: {e}");
            ++i;
        }
    }
    static void dbg<T>(T a, string s = "") {
        Console.WriteLine($"name: {s} value: {a}");
    }
    ////////////////////
    
    static int gcd(int a, int b) {
        while (b != 0) {
            int t = b;
            b = a % b;
            a = t;
        }
        return a;
    }


    public static void Main() {
        
        var sc = new Scanner();
        var wr = new BufferedStdoutWriter();
        var dot = new NumberFormatInfo();
        dot.NumberDecimalSeparator = ".";

        int n = sc.NextInt();
        var ns = new int[n + 1];
        for (int i = 1; i <= n; ++i) {
            ns[i] = sc.NextInt();
        }

        var oddPrefix = new int[n + 1];
        oddPrefix[1] = ns[1];
        for (int i = 2; i <= n; ++i) {
            oddPrefix[i] = oddPrefix[i - 1];
            if (i % 2 == 1) {
                oddPrefix[i] += ns[i];
            }
        }

        //debug(oddPrefix);

        var dptake = new long[n + 1];
        var dpdont = new long[n + 1];
        dptake[2] = ns[2];
        dpdont[2] = ns[1];
        for (int i = 2; i <= n; ++i) {
            if (i % 2 == 0) {
                dptake[i] = ns[i] + dpdont[i - 1];
                dpdont[i] = oddPrefix[i - 1];
            } else {
                dptake[i] = ns[i] + Math.Max(dptake[i - 2], dpdont[i - 2]);
                dpdont[i] = Math.Max(dptake[i - 1], dpdont[i - 1]);
            }
        }

        // debug(dptake);
        // debug(dpdont);

        wr.Write(Math.Max(dptake[n], dpdont[n]));
        wr.Flush();


    }
}