#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include<list>
#include<map>
#include<iterator>
#include<list>
#include<set>
#include<utility>
#include<fstream>
#include<queue>
#include<climits>
#include<cstdio>
#include<time.h>
#include<iomanip>
#include<bitset>
#include<cstring>
#include<cmath>
#include<iomanip>
using namespace std;
#define FAST_IO ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define x40 long long
#define for_(i,t) for(x40 i =0 ; i < t ; i++)
#define fro for
#define itn int
#define for_2(var) x40 T;cin >> T ;for(int var=0;var<T;var++)
#define mod static_cast<x40>(1e9+7)
inline x40 get_size(x40 N);
void make_tree(x40 L, x40 R, x40 curr, vector<x40 > &elements, vector<pair<x40,x40> >  &Tree);
void update_tree(x40 new_val, x40 curr, x40 pos, x40 L, x40 R, vector<pair<x40,x40> >&Tree);
pair<x40,x40> find_min(x40 curr, x40 L, x40 R, x40 l, x40 r,vector<pair<x40,x40 > >  &Tree);
x40 solve(x40 S, x40 E, vector<pair<x40, x40> > &tree,x40 N)
{
	pair<x40, x40> P = find_min(1, 0, N - 1, S, E, tree);
	x40 a, b,c=0,d=0;
	a = P.second - S;
	b = E - P.second;
	if (a)
		c = solve(S, S + a - 1, tree, N);
	if (b)
		d = solve(P.second + 1, E, tree, N);
	return P.first*(a + 1)*(b + 1) + c + d;
}
int main()
{
	FAST_IO
		int N;
	cin >> N;
	vector<x40> v(N);
	vector<pair<x40,x40> >tree(get_size(N) + 1);
	for (int i = 0; i < N; i++)
	{
		cin >> v[i];
	}
	make_tree(0, N - 1, 1, v, tree);
	cout << solve(0, N - 1, tree,N);
	cin >> N;
return 0;
}
//from interval [L,R]
void make_tree(x40 L, x40 R, x40 curr,vector< x40 >&elements,  vector< pair<x40,x40 > > &Tree)
{
	if (L == R)
	{
		Tree[curr].first = elements[L];
		Tree[curr].second = R ;
		return;
	}
	else
	{
		x40 mid = (L + R) / 2;
		make_tree(L, mid, 2 * curr, elements, Tree);
		make_tree(mid + 1, R, 2 * curr + 1, elements, Tree);
		Tree[curr].first=min(Tree[2 * curr].first , Tree[2 * curr + 1].first);
		if (Tree[curr].first == Tree[2 * curr].first)
			Tree[curr].second = Tree[curr * 2].second;
		else
			Tree[curr].second = Tree[curr * 2 + 1 ].second;
	}
	return;
}
//update from [L,R] with value new_val where current node index is curr
void update_tree(x40 new_val, x40 curr, x40 pos, x40 L, x40 R, vector<pair<x40,x40 > >&Tree)
{
	if (L == R)
	{
		Tree[curr].first = new_val;
		return;
	}
	else
	{
	x40 mid = (L + R) / 2;
	if (pos <= mid)
	update_tree(new_val, 2 * curr, pos, L, mid, Tree);
	else
		if (pos>mid)
			update_tree(new_val, 2 * curr + 1, pos, mid + 1, R, Tree);
		Tree[curr].first = min(Tree[2 * curr].first, Tree[2 * curr + 1].first);
		if (Tree[curr].first == Tree[2 * curr].first)
			Tree[curr].second = Tree[2 * curr].second;
		else
			Tree[curr].second = Tree[2 * curr + 1].second;
}
return;
}
//find minimum of range [l,r] and current interval is [L,R]
pair<x40,x40> find_min(x40 curr, x40 L, x40 R, x40 l, x40 r, vector< pair<x40,x40 > > &Tree)
{
	if (r<L || l>R)
	{
	return make_pair(LLONG_MAX,-1);
	}
	else
	{
		if (l <= L && r >= R)
			return Tree[curr];
		else
		{
			x40 mid = (L + R) / 2;
			pair<x40,x40> P1=find_min(2 * curr, L, mid, l, r, Tree),P2= find_min(2 * curr + 1, mid + 1, R, l, r, Tree);
			return P1.first < P2.first ? P1 : P2;
		}
	}
}
inline x40 get_size(x40 N)
{
x40 size = 1;
N--;
while (N)
{
N >>= 1;
size <<= 1;
}
return 2 * size - 1;
}

Measured memory_bytes: 25600