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 Rust (1.15.1) (judge verdict: Accepted)

#![allow(unused_imports, unused_macros, dead_code)]

macro_rules! min {
    (.. $x:expr) => {{
        let mut it = $x.iter();
        it.next().map(|z| it.fold(z, |x, y| min!(x, y)))
    }};
    ($x:expr) => ($x);
    ($x:expr, $($ys:expr),*) => {{
        let t = min!($($ys),*);
        if $x < t { $x } else { t }
    }}
}
macro_rules! max {
    (.. $x:expr) => {{
        let mut it = $x.iter();
        it.next().map(|z| it.fold(z, |x, y| max!(x, y)))
    }};
    ($x:expr) => ($x);
    ($x:expr, $($ys:expr),*) => {{
        let t = max!($($ys),*);
        if $x > t { $x } else { t }
    }}
}


macro_rules! ewriteln {
    ($($args:expr),*) => { let _ = writeln!(&mut std::io::stderr(), $($args),*); };
}
macro_rules! trace {
    ($x:expr) => { ewriteln!(">>> {} = {:?}", stringify!($x), $x) };
    ($($xs:expr),*) => { trace!(($($xs),*)) }
}
macro_rules! put {
    (.. $x:expr) => {{
        let mut it = $x.iter();
        if let Some(x) = it.next() { print!("{}", x); }
        for x in it { print!(" {}", x); }
        println!("");
    }};
    ($x:expr) => { println!("{}", $x) };
    ($x:expr, $($xs:expr),*) => { print!("{} ", $x); put!($($xs),*) }
}

const M: i64 = 1_000_000_007;

use std::i32;
use std::ops::{Range, Index};
use std::cmp::{ min, max };

struct RMQ {
    size: usize, len: usize,
    heap_max: Vec<usize>,
    heap_min: Vec<usize>,
    lefts: Vec<usize>, rights: Vec<usize>,
    reverse_index: Vec<usize>,
}

impl RMQ {

    fn new(v: &Vec<usize>) -> RMQ {
        let n = v.len();
        let size = RMQ::alignment(n);
        let lefts = (0..size).map(|i| RMQ::of_left(i, size/2)).collect();
        let rights = (0..size).map(|i| RMQ::of_right(i, size/2)).collect();
        let mut heap_max = vec![0; size];
        for i in 0..n { heap_max[i + size/2] = v[i]; }
        for i in (0..size/2).rev() { heap_max[i] = max(heap_max[i*2+1], heap_max[i*2+2]); }
        let mut heap_min = vec![0; size];
        for i in 0..n { heap_min[i + size/2] = v[i]; }
        for i in (0..size/2).rev() { heap_min[i] = min(heap_min[i*2+1], heap_min[i*2+2]); }

        let mut reverse_index = vec![0; n];
        for i in 0..n {
            reverse_index[v[i]] = i;
        }

        RMQ {
            size: size,
            len: n,
            heap_max: heap_max,
            heap_min: heap_min,
            lefts: lefts,
            rights: rights,
            reverse_index: reverse_index,
        }
    }

    fn len(&self) -> usize {
        self.len
    }

    fn alignment(n: usize) -> usize {
        let mut m = 1;
        while n > m { m <<= 1; }
        m * 2 - 1
    }

    fn of_left(idx: usize, base: usize) -> usize {
        let mut i = idx; while i < base { i = i * 2 + 1; }
        i - base
    }

    fn of_right(idx: usize, base: usize) -> usize {
        let mut i = idx; while i < base { i = i * 2 + 2; }
        i - base + 1
    }

    fn max(&self, range: Range<usize>) -> usize {
        if range.end == 0 || range.start + 1 > range.end {
            return 0
        }
        if range.start + 1 == range.end {
            return self.heap_max[self.size / 2 + range.start]
        }
        let left = range.start;
        let right = range.end;
        let mut i = self.size / 2 + left;
        while i > 0 {
            let p = (i - 1) / 2;
            if self.lefts[p] == range.start && self.rights[p] <= range.end {
                i = p;
            } else {
                break
            }
        }
        max(self.heap_max[i], self.max(self.rights[i]..right))
    }

    fn max_2nd(&self, range: Range<usize>) -> usize {
        let fu = range.start;
        let ck = range.end;
        let m = self.max(fu..ck);
        let mi = self.reverse_index[m];
        max!(self.max(fu..mi), self.max(mi + 1..ck))
    }
}

impl Index<usize> for RMQ {
    type Output = usize;
    fn index(&self, i: usize) -> &usize {
        &self.heap_max[i + self.size / 2]
    }
}

fn main() {
    let mut sc = Scanner::new();
    let n: usize = sc.cin();
    let p: Vec<usize> = (0..n).map(|_| sc.cin::<usize>() - 1).collect();

    let rmq = RMQ::new(&p);
    let mut ans = 0;

    for i in 0..n {
        let m = p[i];
        let mut left_1st = None;
        let mut left_2nd = None;
        let mut right_1st = None;
        let mut right_2nd = None;

        if i > 0 {
            let mut left = 0;
            let mut right = i;
            for _ in 0..30 {
                let mid = (left + right) / 2;
                if rmq.max(mid..i) < m {
                    right = mid;
                } else {
                    left = mid;
                }
            }
            if p[left] > m {
                left_1st = Some(left);
            }
        }

        if left_1st.is_some() && left_1st.unwrap() > 0 {
            let k = left_1st.unwrap();
            let mut left = 0;
            let mut right = k;
            for _ in 0..30 {
                let mid = (left + right) / 2;
                if rmq.max(mid..k) < m {
                    right = mid;
                } else {
                    left = mid;
                }
            }
            if p[left] > m {
                left_2nd = Some(left);
            }
        }

        if i < n - 1 {
            let mut left = i;  // rmq(i..left) <= m
            let mut right = n;
            for _ in 0..30 {
                let mid = (left + right) / 2;
                if rmq.max(i..mid+1) <= m {
                    left = mid;
                } else {
                    right = mid;
                }
            }
            if left < n - 1 && p[left + 1] > m {
                right_1st = Some(left + 1);
            }
        }

        if right_1st.is_some() && right_1st.unwrap() < n - 1 {
            let k = right_1st.unwrap();
            let mut left = k;
            let mut right = n;
            for _ in 0..30 {
                let mid = (left + right) / 2;
                if rmq.max(k+1..mid+1) <= m {
                    left = mid;
                } else {
                    right = mid;
                }
            }
            if left < n - 1 && p[left + 1] > m {
                right_2nd = Some(left + 1);
            }
        }

        let cases = match (left_2nd, left_1st, right_1st, right_2nd) {
            (Some(a), Some(b), Some(c), Some(d)) => {
                (b - a) * (c - i) + (d - c) * (i - b)
            }
            (None, Some(b), Some(c), Some(d)) => {
                (b + 1) * (c - i) + (d - c) * (i - b)
            }
            (Some(a), Some(b), Some(c), None) => {
                (b - a) * (c - i) + (n - c) * (i - b)
            }
            (None, Some(b), Some(c), None) => {
                (b + 1) * (c - i) + (n - c) * (i - b)
            }
            (Some(a), Some(b), None, None) => {
                (b - a) * (n - i)
            }
            (None, None, Some(c), Some(d)) => {
                (d - c) * (i + 1)
            }
            (None, Some(b), None, None) => {
                (b +1) * (n - i)
            }
            (None, None, Some(c), None) => {
                (n - c) * (i + 1)
            }
            _ => 0
        };
        ans += (p[i] + 1) * cases;

        // trace!(i);
        // trace!(left_1st, left_2nd);
        // trace!(right_1st, right_2nd);
        // trace!(cases);

    }

    put!(ans);
}

use std::io::{self, Write};
use std::str::FromStr;
use std::collections::VecDeque;

struct Scanner { stdin: io::Stdin, buffer: VecDeque<String>, }
impl Scanner {
    fn new() -> Self { Scanner { stdin: io::stdin(), buffer: VecDeque::new() } }
    fn cin<T: FromStr>(&mut self) -> T {
        while self.buffer.len() == 0 {
            let mut line = String::new();
            let _ = self.stdin.read_line(&mut line);
            for w in line.split_whitespace() {
                self.buffer.push_back(String::from(w));
            }
        }
        self.buffer.pop_front().unwrap().parse::<T>().ok().unwrap()
    }
}