#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
#define int ll

#define REP(i,n) for(int i=0;i<n;++i)
#define SORT(name) sort(name.begin(), name.end())
#define ZERO(p) memset(p, 0, sizeof(p))
#define MINUS(p) memset(p, -1, sizeof(p))
#if 0
#  define DBG(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#  define DBG(fmt, ...)
#endif

const ll LLINF = (1LL<<60);
const int INF = (1LL<<30);
const int MOD = 1000000007;
#define MAX_N 200010

template< typename SType>
class SegmentTree
{
    public:
        // 集合の要素 2 つを引数に取リ、その二項演算結果を返す関数
        using Func = function< SType(SType, SType) >;

    public:
        // セグ木を初期化します。
        // サイズは 10^6 くらいまでならいけそう
        // n  : セグ木のサイズ
        // f  : セグ木で判定する関数
        // e : 初期値(単位元)
        SegmentTree(int n, const Func f, const SType &e) : m_F(f), m_E(e) {
            // 要素数は 2 のべき乗じゃないといけないのでそうする
            m_Size = 1;
            while(m_Size < n) { m_Size <<= 1; }
            m_Seg.assign(2 * m_Size, m_E);
        }

        // k 番目の要素に x をセット (0-indexed)
        void Set(int k, const SType &x) { m_Seg[k + m_Size] = x; }

        // セグ木構築 O(N)
        void Build() {
            for(int k = m_Size - 1; k > 0; k--) {
                // 子ノードに対しての演算結果を親ノードに格納
                m_Seg[k] = m_F(m_Seg[2 * k + 0], m_Seg[2 * k + 1]);
            }
        }

        // k 番目の要素を x に変更する O(log N) (0-indexed)
        void Update(int k, const SType &x) {
            k += m_Size;
            m_Seg[k] = x;
            while(k >>= 1) {
                m_Seg[k] = m_F(m_Seg[2 * k + 0], m_Seg[2 * k + 1]);
            }
        }

        // 区間 [a, b) に対して初期設定した関数をした結果を返す O(log N)
        // 開区間なので b は含まれないので注意
        // 0-indexed
        SType Query(int a, int b) {
            SType l = m_E, r = m_E;
            for(a += m_Size, b += m_Size; a < b; a >>= 1, b >>= 1) {
                if(a & 1) l = m_F(l, m_Seg[a++]);
                if(b & 1) r = m_F(m_Seg[--b], r);
            }
            return m_F(l, r);
        }

        SType operator[](const int &k) const
        {
            return m_Seg[k + m_Size];
        }
    public:
        const Func m_F;         // このセグ木で処理する関数（二項演算）
        const SType m_E;        // 初期値(単位元)

        int m_Size;             // セグ木の要素数
        vector< SType > m_Seg;  // セグ木本体。一次元で管理する
};

ll N;
ll A[MAX_N];

ll Pos[MAX_N];      // i のある位置
ll Right[MAX_N];    // i より右にある、 i より小さい数字で一番距離が近いもの
ll Left[MAX_N];

#define SUBMIT

// num より右にある、 num より小さい数字で一番距離が近いもの
ll bin_search_r(SegmentTree<ll>& seg, ll num) {
    ll l = Pos[num] + 1;
    ll r = N - 1;
    while(l + 1 < r) {
        ll mid = (r - l) / 2 + l;
        if(num > seg.Query(l, mid + 1)) {
            r = mid;
        } else {
            l = mid;
        }
    }
    for(int i = l; i <= r; ++i) {
        if(num > A[i]) {
            return A[i];
        }
    }
    assert(false);  // ここには来ないはず
    return -1;
}
// num より左にある、 num より小さい数字で一番距離が近いもの
ll bin_search_l(SegmentTree<ll>& seg, ll num) {
    ll l = 0;
    ll r = Pos[num] - 1;
    while(l + 1 < r) {
        ll mid = (r - l) / 2 + l;
        if(num > seg.Query(mid, r + 1)) {
            l = mid;
        } else {
            r = mid;
        }
    }
    for(int i = r; i >= l; --i) {
        if(num > A[i]) {
            return A[i];
        }
    }
    assert(false);  // ここには来ないはず
    return -1;
}

signed main()
{

    auto Rmq = [](ll a, ll b) -> ll
    {
        return min(a, b);
    };
    MINUS(Pos); MINUS(Right);
    cin >> N;
    SegmentTree<ll> seg(N, Rmq, LLINF);
    REP(i, N) {
        cin >> A[i];
        seg.Set(i, A[i]);
        Pos[A[i]] = i;
    }
    seg.Build();

#ifndef SUBMIT
    ll ans = 0;
    for(ll l = 0; l < N; ++l) {
        for(ll r = l; r < N; ++r) {
            ans += seg.Query(l, r+1);
        }
    }
#endif

    // Right の作成
    for(int i = 1; i <= N; ++i) {
        // 自分の位置より右に自分より小さい数字があるか
        if(i < seg.Query(Pos[i]+1, N)) {
            // ないなら -1
            Right[i] = -1;
        } else {
            Right[i] = bin_search_r(seg, i);
            /*
            for(int j = Pos[i] + 1; j < N; ++j) {
                if(i > A[j]) {
                    Right[i] = A[j];
                    break;
                }
            }
            */
        }
    }
    for(int i = 1; i <= N; ++i) {
        if(i < seg.Query(0, Pos[i])) {
            Left[i] = -1;
        } else {
            Left[i] = bin_search_l(seg, i);
            /*
            for(int j = Pos[i] - 1; j >= 0; --j) {
                if(i > A[j]) {
                    Left[i] = A[j];
                    break;
                }
            }
            */
        }
    }

    ll cand = 0;
    for(int i = 1; i <= N; ++i) {
        ll dist_r, dist_l;
        // 自分より小さい自分より右にある数字のうち、一番近いものまでの距離
        if(Right[i] != -1) {
            dist_r = Pos[Right[i]] - Pos[i];
        } else {
            dist_r = N - Pos[i];
        }
        // 自分より小さい自分より左にある数字のうち、一番近いものまでの距離
        if(Left[i] != -1) {
            dist_l = Pos[i] - Pos[Left[i]];
        } else {
            dist_l = Pos[i] + 1;
        }
        DBG("i: %lld Left[i]: %lld Right[i]: %lld dist_r: %lld dist_l: %lld\n",
                i, Left[i], Right[i], dist_r, dist_l);
        cand += i * dist_r * dist_l;
    }

    printf("%lld\n", cand);
    return 0;
}


Measured memory_bytes: 10624