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++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <functional>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
using namespace std;
template<class T, class Compare = less<T> >
using MaxHeap = priority_queue<T, vector<T>, Compare>;
template<class T, class Compare = greater<T> >
using MinHeap = priority_queue<T, vector<T>, Compare>;
using llong = long long;

//===
template<typename Monoid>
struct SegmentTree {
    using OP = function<Monoid(Monoid, Monoid)>;
    
    vector<Monoid> tree;
    int size;
    const OP f; // bin' operation
    const Monoid e; // neutral element
                                           
    SegmentTree(int nmemb, const Monoid &e, const OP &f):
        f(f),
        e(e)
    {
        size = 1;
        while (size < nmemb) {
            size *= 2;
        }

        tree.assign(2 * size - 1, e);
    }

    void update(int k, Monoid dat) {
        k += size - 1;
        tree[k] = dat;
        
        while(k > 0) {
            k = (k - 1) / 2;
            tree[k] = f(tree[2 * k + 1], tree[2 * k + 2]);
        }
    }

    // [l, r)
    Monoid query(int l, int r) {
        l += size - 1;
        r += size - 1;

        Monoid d = e;
        while (l < r) {
            if (l % 2 == 0) {
                d = f(d, tree[l]);
                l++;
            }
            if (r % 2 == 0) {
                r--;
                d = f(d, tree[r]);
            }

            l = (l - 1) / 2;
            r = (r - 1) / 2;
        }

        return d;
    }

    Monoid operator[] (const int k) { return query(k, k + 1); }
};
//===

struct M {
    llong v;
    llong idx;

    M (llong v, llong idx): v(v), idx(idx) {};
};

llong n;
llong p[100005];
pair<llong, llong> range[100005];
llong sum;

int main() {
    cin >> n;

    SegmentTree<M>seg(n, M(-1, -1),
                  [](M l, M r){
                      if (l.v > r.v) return l;
                      else return r;
                  });

    for (int i = 0; i < n; i++) {
        cin >> p[i];

        seg.update(i, M(p[i], i));
    }

    for (int i = 0; i < n; i++) {

        llong l, r;
        //left
        {
            llong valid = i;
            llong invalid = -1;

            while (valid - invalid > 1) {
                llong mid = (valid + invalid) / 2;

                if (seg.query(mid, i).v > p[i]) {
                    invalid = mid;
                }
                else {
                    valid = mid;
                }
            }

            l = valid;
        }
        //right
        {
            llong valid = i + 1;
            llong invalid = n + 1;

            while (invalid - valid > 1) {
                llong mid = (valid + invalid) / 2;

                if (seg.query(i + 1, mid).v > p[i]) {
                    invalid = mid;
                }
                else {
                    valid = mid;
                }
            }

            if (i < n - 1) r = valid - 1;
            else r = n - 1;
        }

        range[i] = make_pair(l, r);
    }

    llong mv = seg.query(0, n).v;
    for (llong i = 0; i < n; i++) {
        if(p[i] == mv) continue;
        
        llong l, r, ml, mr;
        l = 0; r = n - 1;
        ml = range[i].first;
        mr = range[i].second;

        if (mr < n - 1) {
            // right;
            seg.update(mr + 1, M(-1, -1));
            llong valid = mr + 1;
            llong invalid = n + 1;
            while (invalid - valid > 1) {
                llong mid = (valid + invalid) / 2;

                if (seg.query(i + 1, mid).v > p[i]) {
                    invalid = mid;
                }
                else {
                    valid = mid;
                }
            }
            
            r = valid - 1;
            seg.update(mr + 1, M(p[mr + 1], mr + 1));
        }

        if (ml > 0) {
            // left;
            seg.update(ml - 1, M(-1, -1));
            llong valid = i;
            llong invalid = -1;
            while (valid - invalid > 1) {
                llong mid = (valid + invalid) / 2;

                if (seg.query(mid, i).v > p[i]) {
                    invalid = mid;
                }
                else {
                    valid = mid;
                }
            }
            l = valid;
            seg.update(ml - 1, M(p[ml - 1], ml - 1));
        }

        //printf("%lld: [%lld, %lld, %lld, %lld]\n", p[i], l, ml, mr, r);

        llong mul = 0;

        mul += (r - i + 1) * (i - ml);

        mul += (mr - i) * (i - l + 1);
        
        mul -= (mr - i) * (i - ml);

        sum += mul * p[i];
    }

    cout << sum << endl;

    return 0;
}