use std::borrow::Borrow;
use std::cmp::Ordering::*;
use std::default::Default;
/// Implementation of AVL tree
use std::io::{stdin, Read};
use std::iter::{FromIterator, Iterator};
use std::mem;
use std::ops::Index;

#[derive(Debug)]
pub enum AVLTree<T> {
    Empty,
    NonEmpty(Box<Node<T>>),
}
use AVLTree::*;

#[derive(Debug)]
pub struct Node<T> {
    pub value: T,
    pub left: AVLTree<T>,
    pub right: AVLTree<T>,
    balance_factor: i8,
}

impl<T> Default for AVLTree<T> {
    fn default() -> Self {
        Empty
    }
}

impl<T> AVLTree<T>
where
    T: Ord,
{
    pub fn insert(&mut self, value: T) -> bool {
        self.add(value).0
    }

    fn add(&mut self, value: T) -> (bool, bool) {
        // returns: (inserted, deepened)
        let ret = match *self {
            Empty => {
                let node = Node {
                    value: value,
                    left: Empty,
                    right: Empty,
                    balance_factor: 0,
                };
                *self = NonEmpty(Box::new(node));
                (true, true)
            }
            NonEmpty(ref mut node) => match node.value.cmp(&value) {
                Equal => (false, false),
                Less => {
                    let (inserted, deepened) = node.right.add(value);
                    if deepened {
                        let ret = match node.balance_factor {
                            -1 => (inserted, false),
                            0 => (inserted, true),
                            1 => (inserted, false),
                            _ => unreachable!(),
                        };
                        node.balance_factor += 1;
                        ret
                    } else {
                        (inserted, deepened)
                    }
                }
                Greater => {
                    let (inserted, deepened) = node.left.add(value);
                    if deepened {
                        let ret = match node.balance_factor {
                            -1 => (inserted, false),
                            0 => (inserted, true),
                            1 => (inserted, false),
                            _ => unreachable!(),
                        };
                        node.balance_factor -= 1;
                        ret
                    } else {
                        (inserted, deepened)
                    }
                }
            },
        };
        self.balance();
        ret
    }

    fn balance(&mut self) {
        match *self {
            Empty => (),
            NonEmpty(_) => match self.node().balance_factor {
                -2 => {
                    let lf = self.node().left.node().balance_factor;
                    if lf == -1 || lf == 0 {
                        let (a, b) = if lf == -1 { (0, 0) } else { (-1, 1) };
                        self.rotate_right();
                        self.node().right.node().balance_factor = a;
                        self.node().balance_factor = b;
                    } else if lf == 1 {
                        let (a, b) = match self.node().left.node().right.node().balance_factor {
                            -1 => (1, 0),
                            0 => (0, 0),
                            1 => (0, -1),
                            _ => unreachable!(),
                        };
                        self.node().left.rotate_left();
                        self.rotate_right();
                        self.node().right.node().balance_factor = a;
                        self.node().left.node().balance_factor = b;
                        self.node().balance_factor = 0;
                    } else {
                        unreachable!()
                    }
                }
                2 => {
                    let lf = self.node().right.node().balance_factor;
                    if lf == 1 || lf == 0 {
                        let (a, b) = if lf == 1 { (0, 0) } else { (1, -1) };
                        self.rotate_left();
                        self.node().left.node().balance_factor = a;
                        self.node().balance_factor = b;
                    } else if lf == -1 {
                        let (a, b) = match self.node().right.node().left.node().balance_factor {
                            1 => (-1, 0),
                            0 => (0, 0),
                            -1 => (0, 1),
                            _ => unreachable!(),
                        };
                        self.node().right.rotate_right();
                        self.rotate_left();
                        self.node().left.node().balance_factor = a;
                        self.node().right.node().balance_factor = b;
                        self.node().balance_factor = 0;
                    } else {
                        unreachable!()
                    }
                }
                _ => (),
            },
        }
    }

    fn node(&mut self) -> &mut Node<T> {
        match *self {
            Empty => panic!("call on empty tree"),
            NonEmpty(ref mut v) => v,
        }
    }

    fn right(&mut self) -> &mut Self {
        match *self {
            Empty => panic!("call on empty tree"),
            NonEmpty(ref mut node) => &mut node.right,
        }
    }

    fn left(&mut self) -> &mut Self {
        match *self {
            Empty => panic!("call on empty tree"),
            NonEmpty(ref mut node) => &mut node.left,
        }
    }

    fn rotate_right(&mut self) {
        let mut v = mem::replace(self, Empty);
        let mut left = mem::replace(v.left(), Empty);
        let left_right = mem::replace(left.right(), Empty);
        *v.left() = left_right;
        *left.right() = v;
        *self = left;
    }

    fn rotate_left(&mut self) {
        let mut v = mem::replace(self, Empty);
        let mut right = mem::replace(v.right(), Empty);
        let right_left = mem::replace(right.left(), Empty);
        *v.right() = right_left;
        *right.left() = v;
        *self = right;
    }

    #[cfg(test)]
    fn depth(&self) -> usize {
        match *self {
            Empty => 0,
            NonEmpty(ref v) => std::cmp::max(v.left.depth(), v.right.depth()) + 1,
        }
    }

    pub fn len(&self) -> usize {
        match *self {
            Empty => 0,
            NonEmpty(ref v) => 1 + v.left.len() + v.right.len(),
        }
    }
    pub fn is_empty(&self) -> bool {
        match *self {
            Empty => true,
            _ => false,
        }
    }

    pub fn iter<'a>(&'a self) -> RangeIter<'a, T, &T> {
        self.range(None, None)
    }

    pub fn range<'a, 'b, K>(&'a self, l: Option<&'b K>, r: Option<&'b K>) -> RangeIter<'a, T, &'b K>
    where
        T: Borrow<K>,
        K: ?Sized + Ord,
    {
        RangeIter::new(self, l, r)
    }

    pub fn get<Q>(&self, value: &Q) -> Option<&T>
    where
        T: Borrow<Q>,
        Q: ?Sized + Ord,
    {
        match *self {
            Empty => None,
            NonEmpty(ref node) => match value.cmp(node.value.borrow()) {
                Less => node.left.get(value),
                Equal => Some(&node.value),
                Greater => node.right.get(value),
            },
        }
    }

    #[cfg(test)]
    fn value(&self) -> Option<&T> {
        match *self {
            Empty => None,
            NonEmpty(ref v) => Some(&v.value),
        }
    }
}

pub struct IntoIter<T> {
    stack: Vec<Node<T>>,
}

impl<T> IntoIter<T> {
    pub fn new(tree: AVLTree<T>) -> Self {
        let mut into_iter = IntoIter { stack: Vec::new() };
        into_iter.traverse_left(tree);
        into_iter
    }

    fn traverse_left(&mut self, mut tree: AVLTree<T>) {
        while let NonEmpty(mut node) = tree {
            tree = mem::replace(&mut node.left, Empty);
            self.stack.push(*node);
        }
    }
}

impl<T> Iterator for IntoIter<T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        let mut node = match self.stack.pop() {
            None => return None,
            Some(node) => node,
        };
        self.traverse_left(mem::replace(&mut node.right, Empty));
        Some(node.value)
    }
}

impl<T> IntoIterator for AVLTree<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;
    fn into_iter(self) -> Self::IntoIter {
        IntoIter::new(self)
    }
}

impl<T: Ord> FromIterator<T> for AVLTree<T> {
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
        let mut tree = Empty;
        for v in iter {
            tree.insert(v);
        }
        tree
    }
}

impl<'a, T: Ord> Index<&'a T> for AVLTree<T> {
    type Output = T;
    fn index(&self, index: &T) -> &Self::Output {
        self.get(index).unwrap()
    }
}

pub struct RangeIter<'a, T: 'a, K> {
    end: Option<K>,
    stack: Vec<&'a Node<T>>,
}

impl<'a, 'b, T, K> RangeIter<'a, T, &'b K>
where
    T: Ord + Borrow<K>,
    K: ?Sized + Ord,
{
    fn new(tree: &'a AVLTree<T>, start: Option<&'b K>, end: Option<&'b K>) -> Self {
        let mut iter = RangeIter {
            end: end,
            stack: Vec::new(),
        };
        match start {
            None => iter.traverse_left(tree),
            Some(i) => iter.traverse(tree, i),
        }
        iter
    }
    fn traverse_left(&mut self, mut tree: &'a AVLTree<T>) {
        while let NonEmpty(ref node) = *tree {
            self.stack.push(node);
            tree = &node.left;
        }
    }
    fn traverse(&mut self, tree: &'a AVLTree<T>, start: &K) {
        match *tree {
            Empty => (),
            NonEmpty(ref node) => match start.cmp(node.value.borrow()) {
                Less => {
                    self.stack.push(&node);
                    self.traverse(&node.left, start);
                }
                Equal => self.stack.push(&node),
                Greater => {
                    self.traverse(&node.right, start);
                }
            },
        }
    }
}

impl<'a, 'b, T, K> Iterator for RangeIter<'a, T, &'b K>
where
    T: Ord + Borrow<K>,
    K: ?Sized + Ord,
{
    type Item = &'a T;
    fn next(&mut self) -> Option<Self::Item> {
        match self.stack.pop() {
            None => None,
            Some(ref node) => match self.end {
                None => {
                    self.traverse_left(&node.right);
                    Some(&node.value)
                }
                Some(r) => match r.cmp(&node.value.borrow()) {
                    Greater => {
                        self.traverse_left(&node.right);
                        Some(&node.value)
                    }
                    _ => None,
                },
            },
        }
    }
}

macro_rules! parse {
    ($it: ident) => {
        $it.next().unwrap().parse().unwrap()
    };
    ($it: ident,2) => {
        (parse!($it), parse!($it))
    };
    ($it: ident,3) => {
        (parse!($it), parse!($it), parse!($it))
    };
    ($it: ident,4) => {
        (parse!($it), parse!($it), parse!($it), parse!($it))
    };
    ($it: ident, $n: expr) => {
        (&mut $it).take($n).map(|e| e.parse().unwrap()).collect();
    };
}

use std::cmp::Ordering;
use std::cmp::Ordering::*;
use std::cmp::PartialOrd;

#[derive(PartialEq, Eq)]
struct Rev<T>(T);

impl<T: Ord> PartialOrd for Rev<T> {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(match self.0.cmp(&other.0) {
            Less => Greater,
            Equal => Equal,
            Greater => Less,
        })
    }
}

impl<T: Ord> Ord for Rev<T> {
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

fn solve(s: &str) {
    let mut it = s.split_whitespace();
    let n: usize = parse!(it);
    let p: Vec<i64> = parse!(it, n);
    let mut p: Vec<_> = p.iter().enumerate().map(|(i, &x)| (x, i as i64)).collect();
    p.sort();
    p.reverse();
    let mut ret = 0;
    let mut x = Empty::<Rev<i64>>;
    let mut y = Empty::<i64>;
    for &(pi, i) in p.iter() {
        let kx = Rev(i - 1);
        let ky = i + 1;
        {
            let mut l = x.range(Some(&kx), None);
            let mut r = y.range(Some(&ky), None);
            let l0 = l.next().unwrap_or(&Rev(-1)).0;
            let l1 = l.next().unwrap_or(&Rev(-1)).0;
            let r0 = *r.next().unwrap_or(&(n as i64));
            let r1 = *r.next().unwrap_or(&(n as i64));
            ret += (l0 - l1) * (r0 - i) * pi;
            ret += (i - l0) * (r1 - r0) * pi;
        };
        x.insert(Rev(i));
        y.insert(i);
    }
    println!("{}", ret);
}

fn main() {
    let mut s = String::new();
    stdin().read_to_string(&mut s).unwrap();
    solve(&s);
}

#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn test_input() {
        let s = "
        ";
        solve(s);
    }
}


Measured memory_bytes: 14588