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.Generic;
class Program
{
	static void Main(string[] args)
	{
		int N = int.Parse(Console.ReadLine());
		string[] str = Console.ReadLine().Split();
		int[][]A = new int[N][];
		for(var i=0;i<N;i++){
			int a1 = int.Parse(str[i]);
			A[i] = new int[2]{a1,i};
		}
		Array.Sort(A,(x,y)=>y[0]-x[0]);
		//for(var i=0;i<N;i++){
		//	Console.Error.WriteLine(A[i][0]+" "+A[i][1]);
		//}
		var mset = new Treap<int>();
		mset.Insert(-1);
		mset.Insert(-1);
		mset.Insert(N);
		mset.Insert(N);
		long ans = 0;
		for(var i=0;i<N;i++){
			var t = mset.FindIndex(A[i][1]);
			long a1 = mset[t-1];
			long a2 = mset[t-2];
			long a3 = mset[t];
			long a4 = mset[t+1];
			//Console.Error.WriteLine(mset[t-1]+" "+mset[t-2]+" "+mset[t]+" "+mset[t+1]);
			ans += A[i][0] * ((a1-a2) * (a3 - A[i][1]) + (A[i][1]-a1) * (a4-a3));
			mset.Insert(A[i][1]);
		}
		Console.WriteLine(ans);
	}
}

class Treap<T> where T : IComparable
{
    private class Node
	{
        private static Random g_rand = new Random();
        private readonly int m_rank = g_rand.Next();
        private readonly T m_value;
        private Node m_lch;
        private Node m_rch;
        private int m_count;
        public Node(T value){
            m_value = value;
            m_count = 1;
        }
        private static int Count(Node node){
            return (node != null) ? node.m_count : 0;
        }
        private Node Update(){
            m_count = Count(m_lch) + Count(m_rch) + 1;
            return this;
        }
        public static Node Merge(Node a, Node b){
            if (a == null) { return b; }
            if (b == null) { return a; }
            if (a.m_rank < b.m_rank){
                a.m_rch = Merge(a.m_rch, b);
                return a.Update();
            } else {
                b.m_lch = Merge(a, b.m_lch);
                return b.Update();
            }
        }
        public static Tuple<Node, Node> Split(Node t, int k){
            if (t == null) { return new Tuple<Node, Node>(null, null); }
            if (k <= Count(t.m_lch)){
                var pair = Split(t.m_lch, k);
                t.m_lch = pair.Item2;
                return new Tuple<Node, Node>(pair.Item1, t.Update());
            } else {
                var pair = Split(t.m_rch, k - Count(t.m_lch) - 1);
                t.m_rch = pair.Item1;
                return new Tuple<Node, Node>(t.Update(), pair.Item2);
            }
        }
        public int FindIndex(T value){
            int L = Count(m_lch);
            if (value.CompareTo(m_value) < 0){
                return (m_lch != null) ? m_lch.FindIndex(value) : 0;
            } else if (value.CompareTo(m_value) > 0) {
                return (m_rch != null) ? m_rch.FindIndex(value) + L + 1 : L + 1;
            } else {
                return L;
            }
        }
        public T this[int i]{
            get {
                int L = Count(m_lch);
                if (i < L){
                    return m_lch[i];
                } else if (i > L){
                    return m_rch[i - L - 1];
                } else {
                    return m_value;
                }
            }
        }
    }
    private Node node;
    public void Insert(T value){
        if (node != null){
            int k = node.FindIndex(value);
            var pair = Node.Split(node, k);
            node = Node.Merge(Node.Merge(pair.Item1, new Node(value)), pair.Item2);
        } else {
            node = new Node(value);
        }
    }
    public int FindIndex(T value){
        return node.FindIndex(value);
    }
    public T this[int i]{
        get{
            return node[i];
        }
    }
}