/*------------------------------------------------------------------*/
/*------------------------- begin template -------------------------*/
/*------------------------------------------------------------------*/

// ref: tanakh <https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8>
// diff: using Parser
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut parser = Parser::from_str($s);
        input_inner!{parser, $($r)*}
    };
    (parser = $parser:ident, $($r:tt)*) => {
        input_inner!{$parser, $($r)*}
    };
    (new_stdin_parser = $parser:ident, $($r:tt)*) => {
        let stdin = std::io::stdin();
        let reader = std::io::BufReader::new(stdin.lock());
        let mut $parser = Parser::new(reader);
        input_inner!{$parser, $($r)*}
    };
    ($($r:tt)*) => {
        input!{new_stdin_parser = parser, $($r)*}
    };
}

macro_rules! input_inner {
    ($parser:ident) => {};
    ($parser:ident, ) => {};
    ($parser:ident, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($parser, $t);
        input_inner!{$parser $($r)*}
    };
}

macro_rules! read_value {
    ($parser:ident, ( $($t:tt),* )) => {
        ( $(read_value!($parser, $t)),* )
    };
    ($parser:ident, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($parser, $t)).collect::<Vec<_>>()
    };
    ($parser:ident, chars) => {
        read_value!($parser, String).chars().collect::<Vec<char>>()
    };
    ($parser:ident, char_) => {
        read_value!($parser, String).chars().collect::<Vec<char>>()[0]
    };
    ($parser:ident, usize1) => {
        read_value!($parser, usize) - 1
    };
    ($parser:ident, i64_) => {
        $parser.fast_i64()
    };
    ($parser:ident, usize_) => {
        $parser.fast_i64() as usize
    };
    ($parser:ident, usize1_) => {
        ($parser.fast_i64() - 1) as usize
    };
    ($parser:ident, $t:ty) => {
        $parser.next::<$t>().expect("Parse error")
    };
}

use std::io;
use std::io::BufRead;
use std::str;

// ref: tatsuya6502 <https://qiita.com/tatsuya6502/items/cd448486f7ef7b5b8c7e>
// ref: wariuni <https://qiita.com/tatsuya6502/items/cd448486f7ef7b5b8c7e#comment-7040a5ae96305e884eb9>
// diff: using std::io::BufRead::fill_buf()
pub struct Parser<R> {
    pub reader: R,
    buf: Vec<u8>,
    pos: usize,
}

impl Parser<io::Empty> {
    pub fn from_str(s: &str) -> Parser<io::Empty> {
        Parser {
            reader: io::empty(),
            buf: s.as_bytes().to_vec(),
            pos: 0,
        }
    }
}

impl<R: BufRead> Parser<R> {
    pub fn new(reader: R) -> Parser<R> {
        Parser {
            reader: reader,
            buf: vec![],
            pos: 0,
        }
    }
    pub fn update_buf(&mut self) {
        self.buf.clear();
        self.pos = 0;
        loop {
            let (len, complete) = {
                let buf2 = self.reader.fill_buf().unwrap();
                self.buf.extend_from_slice(buf2);
                let len = buf2.len();
                (len, buf2[len - 1] <= 0x20)
            };
            self.reader.consume(len);
            if complete {
                break;
            }
        }
    }
    pub fn next<T: str::FromStr>(&mut self) -> Result<T, T::Err> {
        loop {
            let mut begin = self.pos;
            while begin < self.buf.len() && (self.buf[begin] <= 0x20) {
                begin += 1;
            }
            let mut end = begin;
            while end < self.buf.len() && (self.buf[end] > 0x20) {
                end += 1;
            }
            if begin != self.buf.len() {
                self.pos = end;
                return unsafe { str::from_utf8_unchecked(&self.buf[begin..end]) }.parse::<T>();
            } else {
                self.update_buf();
            }
        }
    }
    pub fn fast_i64(&mut self) -> i64 {
        loop {
            let mut begin = self.pos;
            while begin < self.buf.len() && (self.buf[begin] <= 0x20) {
                begin += 1;
            }
            if begin == self.buf.len() {
                self.update_buf();
                continue;
            }
            let mut res = 0;
            let (is_positive, mut end) = match self.buf[begin] {
                b'+' => (true, begin + 1),
                b'-' => (false, begin + 1),
                _ => (true, begin),
            };
            while end < self.buf.len() && (self.buf[end] > 0x20) {
                res = res * 10 + (self.buf[end] as i64 - '0' as i64);
                end += 1;
            }
            if begin != self.buf.len() {
                self.pos = end;
                return if is_positive { res } else { -res };
            } else {
                self.update_buf();
            }
        }
    }
}

#[allow(unused_imports)]
use std::cmp::*;

#[derive(Debug)]
pub struct MySet<T> {
    root: Option<Box<MySetNode<T>>>,
}

#[derive(Debug)]
enum MySetNode<T> {
    Node {
        left_node: Box<MySetNode<T>>,
        right_node: Box<MySetNode<T>>,
        lower: T,
        upper: T,
        rank: usize,
        num: usize,
    },
    Leaf {
        val: T,
    },
}

impl<T: Clone + Copy + PartialEq + Eq + PartialOrd + Ord + std::fmt::Debug> MySet<T> {
    pub fn new() -> MySet<T> {
        MySet { root: None }
    }
    pub fn insert(&mut self, x: T) {
        *self = match self.root.take() {
            Some(root) => MySet {
                root: Some(Box::new(MySetNode::insert(*root, x))),
            },
            None => MySet {
                root: Some(Box::new(MySetNode::Leaf { val: x })),
            },
        };
    }
    pub fn delete(&mut self, x: T) {
        *self = match self.root.take() {
            Some(root) => {
                let root = MySetNode::delete(*root, x);
                match root {
                    Some(root) => MySet {
                        root: Some(Box::new(root)),
                    },
                    None => MySet { root: None },
                }
            }
            None => MySet { root: None },
        };
    }
    pub fn next(&self, x: T) -> Option<T> {
        match *&self.root {
            Some(ref root) => MySetNode::next(root.as_ref(), x),
            None => None,
        }
    }
    pub fn prev(&self, x: T) -> Option<T> {
        match *&self.root {
            Some(ref root) => MySetNode::prev(root.as_ref(), x),
            None => None,
        }
    }
}

impl<T: Clone + Copy + PartialEq + Eq + PartialOrd + Ord + std::fmt::Debug> MySetNode<T> {
    fn new(left: MySetNode<T>, right: MySetNode<T>) -> MySetNode<T> {
        // assert!(left.rank() + 1 == right.rank() || left.rank() == right.rank() || left.rank() == right.rank() + 1, "left = {:?}, right = {:?}", left, right);
        let lower = left.get_lower();
        let upper = right.get_upper();
        let rank = 1 + max(left.rank(), right.rank());
        let num = left.num() + right.num();
        MySetNode::Node {
            left_node: Box::new(left),
            right_node: Box::new(right),
            lower: lower,
            upper: upper,
            rank: rank,
            num: num,
        }
    }
    fn get_lower(&self) -> T {
        match *self {
            MySetNode::Node {
                left_node: _,
                right_node: _,
                lower: ref lower,
                upper: _,
                rank: _,
                num: _,
            } => *lower,
            MySetNode::Leaf { val: ref val } => *val,
        }
    }
    fn get_upper(&self) -> T {
        match *self {
            MySetNode::Node {
                left_node: _,
                right_node: _,
                lower: _,
                upper: ref upper,
                rank: _,
                num: _,
            } => *upper,
            MySetNode::Leaf { val: ref val } => *val,
        }
    }
    fn rank(&self) -> usize {
        match *self {
            MySetNode::Node {
                left_node: _,
                right_node: _,
                lower: _,
                upper: _,
                rank: ref rank,
                num: _,
            } => *rank,
            MySetNode::Leaf { val: _ } => 1,
        }
    }
    fn num(&self) -> usize {
        match *self {
            MySetNode::Node {
                left_node: _,
                right_node: _,
                lower: _,
                upper: _,
                rank: _,
                num: ref num,
            } => *num,
            MySetNode::Leaf { val: _ } => 1,
        }
    }
    fn get_left_rank(&self) -> usize {
        match *self {
            MySetNode::Node {
                left_node: ref left_node,
                right_node: _,
                lower: _,
                upper: _,
                rank: _,
                num: _,
            } => left_node.rank(),
            _ => 0,
        }
    }
    fn get_right_rank(&self) -> usize {
        match *self {
            MySetNode::Node {
                left_node: _,
                right_node: ref right_node,
                lower: _,
                upper: _,
                rank: _,
                num: _,
            } => right_node.rank(),
            _ => 0,
        }
    }
    fn unsafe_destruct(node: MySetNode<T>) -> (MySetNode<T>, MySetNode<T>) {
        match node {
            MySetNode::Node {
                left_node: left_node,
                right_node: right_node,
                lower: _,
                upper: _,
                rank: _,
                num: _,
            } => (*left_node, *right_node),
            _ => panic!(),
        }
    }
    fn balance(node: MySetNode<T>) -> MySetNode<T> {
        match node {
            MySetNode::Node {
                left_node: left_node,
                right_node: right_node,
                lower: lower,
                upper: upper,
                rank: rank,
                num: num,
            } => {
                if left_node.rank() >= right_node.rank() + 2 {
                    if left_node.get_left_rank() >= left_node.get_right_rank() {
                        let (node_l, node_r) = (*left_node, *right_node);
                        let (node_ll, node_lr) = MySetNode::unsafe_destruct(node_l);
                        MySetNode::new(node_ll, MySetNode::new(node_lr, node_r))
                    } else {
                        let (node_l, node_r) = (*left_node, *right_node);
                        let (node_ll, node_lr) = MySetNode::unsafe_destruct(node_l);
                        let (node_lrl, node_lrr) = MySetNode::unsafe_destruct(node_lr);
                        MySetNode::new(
                            MySetNode::new(node_ll, node_lrl),
                            MySetNode::new(node_lrr, node_r),
                        )
                    }
                } else if left_node.rank() + 2 <= right_node.rank() {
                    if right_node.get_left_rank() >= right_node.get_right_rank() {
                        let (node_l, node_r) = (*left_node, *right_node);
                        let (node_rl, node_rr) = MySetNode::unsafe_destruct(node_r);
                        let (node_rll, node_rlr) = MySetNode::unsafe_destruct(node_rl);
                        MySetNode::new(
                            MySetNode::new(node_l, node_rll),
                            MySetNode::new(node_rlr, node_rr),
                        )
                    } else {
                        let (node_l, node_r) = (*left_node, *right_node);
                        let (node_rl, node_rr) = MySetNode::unsafe_destruct(node_r);
                        MySetNode::new(MySetNode::new(node_l, node_rl), node_rr)
                    }
                } else {
                    MySetNode::Node {
                        left_node: left_node,
                        right_node: right_node,
                        lower: lower,
                        upper: upper,
                        rank: rank,
                        num: num,
                    }
                }
            }
            MySetNode::Leaf { val } => MySetNode::Leaf { val: val },
        }
    }
    fn insert(node: MySetNode<T>, x: T) -> MySetNode<T> {
        match node {
            MySetNode::Node {
                left_node: left_node,
                right_node: right_node,
                lower: lower,
                upper: upper,
                rank: rank,
                num: num,
            } => {
                if x < right_node.get_lower() {
                    let left_node = MySetNode::insert(*left_node, x);
                    MySetNode::balance(MySetNode::new(left_node, *right_node))
                } else {
                    let right_node = MySetNode::insert(*right_node, x);
                    MySetNode::balance(MySetNode::new(*left_node, right_node))
                }
            }
            MySetNode::Leaf { val } => match val.cmp(&x) {
                Ordering::Less => {
                    MySetNode::new(MySetNode::Leaf { val: val }, MySetNode::Leaf { val: x })
                }
                Ordering::Equal => MySetNode::Leaf { val: x },
                Ordering::Greater => {
                    MySetNode::new(MySetNode::Leaf { val: x }, MySetNode::Leaf { val: val })
                }
            },
        }
    }
    fn delete(node: MySetNode<T>, x: T) -> Option<MySetNode<T>> {
        match node {
            MySetNode::Node {
                left_node: left_node,
                right_node: right_node,
                lower: lower,
                upper: upper,
                rank: rank,
                num: num,
            } => {
                if left_node.get_lower() <= x && x <= left_node.get_upper() {
                    let left_node = MySetNode::delete(*left_node, x);
                    match left_node {
                        Some(left_node) => {
                            Some(MySetNode::balance(MySetNode::new(left_node, *right_node)))
                        }
                        None => Some(*right_node),
                    }
                } else if right_node.get_lower() <= x && x <= right_node.get_upper() {
                    let right_node = MySetNode::delete(*right_node, x);
                    match right_node {
                        Some(right_node) => {
                            Some(MySetNode::balance(MySetNode::new(*left_node, right_node)))
                        }
                        None => Some(*left_node),
                    }
                } else {
                    Some(MySetNode::new(*left_node, *right_node))
                }
            }
            MySetNode::Leaf { val } => match val.cmp(&x) {
                Ordering::Less => Some(MySetNode::Leaf { val: x }),
                Ordering::Equal => None,
                Ordering::Greater => Some(MySetNode::Leaf { val: x }),
            },
        }
    }
    fn next(node: &MySetNode<T>, x: T) -> Option<T> {
        match *node {
            MySetNode::Node {
                left_node: ref left_node,
                right_node: ref right_node,
                lower: _,
                upper: _,
                rank: _,
                num: _,
            } => {
                if right_node.get_lower() <= x {
                    MySetNode::next(right_node, x)
                } else {
                    let t = MySetNode::next(left_node, x);
                    if t.is_some() {
                        t
                    } else {
                        Some(right_node.get_lower())
                    }
                }
            }
            MySetNode::Leaf { val: ref val } => {
                if x < *val {
                    Some(*val)
                } else {
                    None
                }
            }
        }
    }
    fn prev(node: &MySetNode<T>, x: T) -> Option<T> {
        match *node {
            MySetNode::Node {
                left_node: ref left_node,
                right_node: ref right_node,
                lower: _,
                upper: _,
                rank: _,
                num: _,
            } => {
                if x <= left_node.get_upper() {
                    MySetNode::prev(left_node, x)
                } else {
                    let t = MySetNode::prev(right_node, x);
                    if t.is_some() {
                        t
                    } else {
                        Some(left_node.get_upper())
                    }
                }
            }
            MySetNode::Leaf { val: ref val } => {
                if *val < x {
                    Some(*val)
                } else {
                    None
                }
            }
        }
    }
}

fn main() {
    input! {
        new_stdin_parser = parser,
    }
    let res = solve(&mut parser);
    print!("{}", res);
}

/*------------------------------------------------------------------*/
/*-------------------------- end template --------------------------*/
/*------------------------------------------------------------------*/

use std::fmt::Write;
fn solve<R: BufRead>(parser: &mut Parser<R>) -> String {
    let mut buf = String::new();
    input! {
        parser = parser,
        n: usize,
        xs: [usize; n],
    }
    let mut set = MySet::new();
    let mut ys = vec![0; n + 1];
    for (i, &x) in xs.iter().enumerate() {
        ys[x] = i + 1;
    }
    // // eprintln!("ys = {:?}", ys);
    for i in 0..n + 1 + 1 {
        set.insert(i);
    }
    let mut res = 0i64;
    for &i in &ys[1..] {
        // // eprintln!("i = {}, xs[i-1] = {}", i, xs[i - 1]);

        let l1 = set.prev(i).unwrap();
        // // eprintln!("l1 = {}", l1);
        if l1 != 0 {
            let l2 = set.prev(l1).unwrap();
            // // eprintln!("l2 = {}", l2);
            let r = set.next(i).unwrap();
            let t = (r - i) as i64 * (l1 - l2) as i64;
            res += xs[i - 1] as i64 * t;
        }

        let r1 = set.next(i).unwrap();
        if r1 != n + 1 {
            let r2 = set.next(r1).unwrap();
            let l = set.prev(i).unwrap();
            let t = (i - l) as i64 * (r2 - r1) as i64;
            res += xs[i - 1] as i64 * t;
        }
        set.delete(i);
    }
    writeln!(buf, "{}", res);
    buf
}


Measured memory_bytes: 18684