Problem:
Score: 500 points

Problem Statement

Given is a permutation P of \{1, 2, \ldots, N\}.

For a pair (L, R) (1 \le L \lt R \le N), let X_{L, R} be the second largest value among P_L, P_{L+1}, \ldots, P_R.

Find \displaystyle \sum_{L=1}^{N-1} \sum_{R=L+1}^{N} X_{L,R}.

Constraints

2 \le N \le 10^5

1 \le P_i \le N

P_i \neq P_j (i \neq j)

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
P_1 P_2 \ldots P_N

Output

Print \displaystyle \sum_{L=1}^{N-1} \sum_{R=L+1}^{N} X_{L,R}.

Sample Input 1

3
2 3 1

Sample Output 1

5

X_{1, 2} = 2, X_{1, 3} = 2, and X_{2, 3} = 1, so the sum is 2 + 2 + 1 = 5.

Sample Input 2

5
1 2 3 4 5

Sample Output 2

30

Sample Input 3

8
8 2 7 3 4 5 6 1

Sample Output 3

136

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;   
 
class Solver
    {
        /*
         * https://atcoder.jp/contests/abc140/tasks/abc140_e
         * 
         */
        public void Solve()
        {
            var n = u.readInt();
            var P = u.readIntArrayBySplit();
            //Console.WriteLine(P.AsJoinedString());
            var ans = 0L;
 
            var sortedP = P.Select((v, i) => new { V = v, N = i }).OrderByDescending(x => x.V);
            var S = new SortedArray<int>(n+4);
            S.Insert(-1);
            S.Insert(-1);
            S.Insert(n);
            S.Insert(n);
 
            //var D = new SortedList<long,long>();
            //D.Add(-1, -1);
            //D.Add(-2, -1);
            //D.Add(n, n);
            //D.Add(n+1,n);
 
            foreach (var elem in sortedP)
            {
                var i = S.Insert(elem.N);
                //var ndx = S.IndexOfKey(elem.N);
                //var w = D.Values[ndx - 2];
                //var x = D.Values[ndx - 1];
                //var y = D.Values[ndx + 1];
                //var z = D.Values[ndx + 2];
                var w = S[i - 2];
                var x = S[i - 1];
                var y = S[i + 1];
                var z = S[i + 2];
                
                var c = (x - w) * (y - elem.N) + (elem.N - x) * (z - y);
                //Console.WriteLine(string.Format("w;{0} x:{1} i:{2} y:{3} z{4} c;{5} P:{6} cP:{7}", w, x,elem.N, y, z,c,elem.V, c * elem.V));
                ans += (long)c * (long)elem.V;
                
            }
            Console.WriteLine(ans);
        }
        static void Main()
        {
            var solver = new Solver();
            solver.Solve();
        }
    }
 
    static class u
    {
        public static void outA(int[] A) { Console.WriteLine(string.Join(" ", A)); }
        static public string AsJoinedString<T>(this IEnumerable<T> ie, string st = " ") { return string.Join(st, ie); }
        public static int readInt() { return int.Parse(Console.ReadLine()); }
        public static int[] readIntArrayBySplit() { return Console.ReadLine().Split(' ').Select(s => int.Parse(s)).ToArray(); }
 
    }
class SortedArray<T>:IEnumerable<T>
      where T : IComparable<T>
    {
        #region フィールド
 
        List<T> buffer;
        internal T this[int x]
        {
            set { this.buffer[x] = value; }
            get { return this.buffer[x]; }
        }
 
 
        #endregion
        #region 初期化
 
        public SortedArray() : this(256) { }
 
        public SortedArray(int capacity)
        {
            this.buffer = new List<T>(capacity);
        }
 
        #endregion
        #region 要素の挿入・削除・検索
 
        /// <summary>
        /// 要素の挿入。
        /// </summary>
        /// <param name="elem">挿入する要素</param>
        public int Insert(T elem)
        {
            if (this.buffer.Count == 0)
            {
                this.buffer.Add(elem);
                return 0;
            }
 
            int r = this.buffer.Count - 1;
            int l = 0;
            int comp;
            while (l < r)
            {
                int m = (r + l) >> 1;
                comp = this.buffer[m].CompareTo(elem);
                if (comp > 0) r = m - 1;
                else if (comp < 0) l = m + 1;
                else
                {
                    this.buffer.Insert(m, elem);
                    return m;
                }
            }
 
            comp = this.buffer[l].CompareTo(elem);
            if (comp < 0)
            {
                this.buffer.Insert(l + 1, elem);
                return l + 1;
            }
            else if (comp > 0)
            {
                this.buffer.Insert(l, elem);
                return l;
            }
            else
            {
                this.buffer.Insert(l, elem);
                return l;
            }
        }
 
        /// <summary>
        /// 要素の検索。
        /// </summary>
        /// <param name="elem">検索する要素</param>
        /// <returns>要素の位置（見つからなかった場合、配列長）</returns>
        public int IndexOf(T elem)
        {
            if (this.buffer.Count == 0)
                return 0;
 
            int r = this.buffer.Count - 1;
            int l = 0;
            while (l < r)
            {
                int m = (r + l) >> 1;
                int comp = this.buffer[m].CompareTo(elem);
                if (comp > 0) r = m - 1;
                else if (comp < 0) l = m + 1;
                else return m;
            }
 
            if (this.buffer[l].CompareTo(elem) == 0)
                return l;
            return this.buffer.Count;
        }
 
        /// <summary>
        /// テーブル中に要素が含まれているかどうか判別。
        /// </summary>
        /// <param name="elem">探したい要素</param>
        /// <returns>含まれていれば true</returns>
        public bool Contains(T elem)
        {
            return this.IndexOf(elem) != this.buffer.Count;
        }
 
        /// <summary>
        /// テーブル中の要素を検索。
        /// </summary>
        /// <param name="elem">探したい要素</param>
        /// <returns>含まれていればその要素を、なければ default(T)</returns>
        public T Find(T elem)
        {
            int i = this.IndexOf(elem);
            if (i == this.buffer.Count)
                return default(T);
            return this.buffer[i];
        }
 
        /// <summary>
        /// 要素の削除。
        /// </summary>
        /// <param name="elem">削除する要素</param>
        public void Erase(T elem)
        {
            int i = this.IndexOf(elem);
            if (i < this.buffer.Count)
                this.buffer.RemoveAt(i);
        }
 
        #endregion
        #region IEnumerable<T> メンバ
 
        public IEnumerator<T> GetEnumerator()
        {
            for (int i = 0; i < this.buffer.Count; ++i)
                yield return this.buffer[i];
        }
 
 
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
 
        #endregion
    }