Language: C++

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <vector>
#include <map>
#include <set>
#include <deque>
#include <list>
#include <stack>
#include <queue>
#include <complex>
#include <ctime>
#include<cstdlib>
#define _USE_MATH_DEFINES
#include <math.h>
#include<cmath>
#include <cstdarg> 
#include <iomanip>

#include<unordered_map>
#include<unordered_set>
//#include <arra.y>

//#define  NDEBUG
#include <assert.h>

using namespace std;

#define dprint(Exp,...) if(Exp){fprintf(stderr, __VA_ARGS__);}
#define printe(...) fprintf(stderr, __VA_ARGS__);
#define PrtExp(_Exp)  cerr<< #_Exp <<" = "<< (_Exp)
#define PrtExpN(_Exp)  cerr<< #_Exp <<" = "<< (_Exp) <<"\n"

#define SINT(n) scanf("%d",&n);
#define SINT2(n,m) scanf("%d %d",&n,&m);
#define SINT3(n,m,o) scanf("%d %d %d",&n,&m,&o);
#define SINT4(n,m,o,p) scanf("%d %d %d %d",&n,&m,&o,&p);
#define SINT5(n,m,o,p,q) scanf("%d %d %d %d %d",&n,&m,&o,&p,&q);
//#define SLL(n) scanf("%I64d",&n);
#define SLL(n) scanf("%lld",&n);
#define SLL2(n,m) scanf("%lld %lld",&n,&m);
#define SLL3(n,m,o) scanf("%lld %lld %lld",&n,&m,&o);
#define SST(s) scanf("%s",s);
#define SCH(c) scanf("%c",&c);

#define GC() getchar();

#define PINT(n) printf("%d",(int)(n));
#define PINT2(n,m) printf("%d %d",(int)(n),(int)(m));
#define PINT3(n,m,l) printf("%d %d %d",(int)(n),(int)(m),(int)(l));
//#define PLL(n) printf("%I64d",(long long)(n));
#define PLL(n) printf("%lld",(long long)(n));
#define PST(s) printf("%s",(s));
#define PCH(s) printf("%c",(s));

#define PINTN(n) printf("%d\n",(int)(n));
#define PINT2N(n,m) printf("%d %d\n",(int)(n),(int)(m));
#define PINT3N(n,m,l) printf("%d %d %d\n",(int)(n),(int)(m),(int)(l));
//#define PLLN(n) printf("%I64d\n",(long long)(n));
#define PLLN(n) printf("%lld\n",(long long)(n));
#define PSTN(s) printf("%s\n",(s));
#define PCHN(s) printf("%c\n",(s));

#define PSP() printf(" ");
#define PN() printf("\n");

#define PC(c) putchar(c);
#define CSP (' ')
#define SN ("\n")

#define rep(i,a) for(i=0;i<a;i++)
#define reP(i,a) for(i=0;i<=a;i++)
#define Rep(i,a) for(i=a-1;i>=0;i--)
#define ReP(i,a) for(i=a;i>=0;i--)

#define rEp(i,a) for(int i=0;i<a;i++)
#define rEP(i,a) for(int i=0;i<=a;i++)
#define REp(i,a) for(int i=a-1;i>=0;i--)
#define REP(i,a) for(int i=a;i>=0;i--)

#define repft(i,a,b) for(i=a;i<b;i++)
#define repfT(i,a,b) for(i=a;i<=b;i++)
#define Repft(i,a,b) for(i=a-1;i>=b;i--)
#define RepfT(i,a,b) for(i=a;i>=b;i--)

#define foreach(a,it) for(auto it = a.begin(); it != a.end(); ++it)

#define FILL(a,v) fill(begin(a),end(a), v)
#define FILL0(a) memset(a,0,sizeof(a))
#define FILL1(a) memset(a,-1,sizeof(a))

typedef long long ll;
typedef unsigned long ul;
typedef pair<int, int> Pi;
typedef pair<ll, ll>   Pl;


const int INF = 0x1f1f1f1f;//522,133,279
const ll INFLL = 0x1f1f1f1f1f1f1f1fLL;//2,242,545,357,980,376,863

template <class A, class B> inline ostream& operator<<(ostream& st, const pair<A, B>& P) { return st << "(" << P.first << "," << P.second << ")"; };
template <class A, class B> inline pair<A, B> operator+(const pair<A, B>& P, const pair<A, B>& Q) { return pair<A, B>(P.first + Q.first, P.second + Q.second); };
template <class A, class B> inline pair<A, B> operator-(const pair<A, B>& P, const pair<A, B>& Q) { return pair<A, B>(P.first - Q.first, P.second - Q.second); };

ll bitcount(ll bits) {
	bits = (bits & 0x5555555555555555) + (bits >> 1 & 0x5555555555555555);
	bits = (bits & 0x3333333333333333) + (bits >> 2 & 0x3333333333333333);
	bits = (bits & 0x0f0f0f0f0f0f0f0f) + (bits >> 4 & 0x0f0f0f0f0f0f0f0f);
	bits = (bits & 0x00ff00ff00ff00ff) + (bits >> 8 & 0x00ff00ff00ff00ff);
	bits = (bits & 0x0000ffff0000ffff) + (bits >> 16 & 0x0000ffff0000ffff);
	return (bits & 0x00000000ffffffff) + (bits >> 32 & 0x00000000ffffffff);
}




// A utility function to get minimum of two numbers
int minVal(int x, int y) { return (x < y) ? x : y; }

// A utility function to get the middle index from corner indexes.
int getMid(int s, int e) { return s + (e - s) / 2; }

/*  A recursive function to get the minimum value in a given range
of array indexes. The following are parameters for this function.

st    --> Pointer to segment tree
index --> Index of current node in the segment tree. Initially
0 is passed as root is always at index 0
ss & se  --> Starting and ending indexes of the segment represented
by current node, i.e., st[index]
qs & qe  --> Starting and ending indexes of query range */
int RMQUtil(int *st, int ss, int se, int qs, int qe, int index)
{
	// If segment of this node is a part of given range, then return
	//  the min of the segment
	if (qs <= ss && qe >= se)
		return st[index];

	// If segment of this node is outside the given range
	if (se < qs || ss > qe)
		return INT_MAX;

	// If a part of this segment overlaps with the given range
	int mid = getMid(ss, se);
	return minVal(RMQUtil(st, ss, mid, qs, qe, 2 * index + 1),
		RMQUtil(st, mid + 1, se, qs, qe, 2 * index + 2));
}

// Return minimum of elements in range from index qs (quey start) to
// qe (query end).  It mainly uses RMQUtil()
int RMQ(int *st, int n, int qs, int qe)
{
	// Check for erroneous input values
	if (qs < 0 || qe > n - 1 || qs > qe)
	{
		printf("Invalid Input");
		return -1;
	}

	return RMQUtil(st, 0, n - 1, qs, qe, 0);
}

// A recursive function that constructs Segment Tree for array[ss..se].
// si is index of current node in segment tree st
int constructSTUtil(int arr[], int ss, int se, int *st, int si)
{
	// If there is one element in array, store it in current node of
	// segment tree and return
	if (ss == se)
	{
		st[si] = arr[ss];
		return arr[ss];
	}

	// If there are more than one elements, then recur for left and
	// right subtrees and store the minimum of two values in this node
	int mid = getMid(ss, se);
	st[si] = minVal(constructSTUtil(arr, ss, mid, st, si * 2 + 1),
		constructSTUtil(arr, mid + 1, se, st, si * 2 + 2));
	return st[si];
}

/* Function to construct segment tree from given array. This function
allocates memory for segment tree and calls constructSTUtil() to
fill the allocated memory */
int *constructST(int arr[], int n)
{
	// Allocate memory for segment tree

	//Height of segment tree
	int x = (int)(ceil(log2(n)));

	// Maximum size of segment tree
	int max_size = 2 * (int)pow(2, x) - 1;

	int *st = new int[max_size];

	// Fill the allocated memory st
	constructSTUtil(arr, 0, n - 1, st, 0);

	// Return the constructed segment tree
	return st;
}






int a[200010];
int A[200010];

int main() {

	int N;
	ll ret = 0;
	cin >> N;
	int i, j;

	a[0] = 0;
	rep(i, N) {
		SINT(a[i + 1]);
	}
	a[N + 1] = 0;
	rep(i, N + 2)A[i] = a[i];
	reverse(A, A + N + 2);

	int *st = constructST(a, N + 2);
	int *ST = constructST(A, N + 2);

	repfT(i, 1, N) {
		ll llen,rlen;
		int l = 0, r = i-1, m, v;
		//cerr << a[i] << endl;

		while (l + 1 < r) {
			m = (l + r) / 2;
			v = RMQ(st, N + 2, m, i-1);
			//cout << "Min[" << m << "," << (i-1) << "]=" << v << endl;
			if (v > a[i]) r = m;
			else          l = m;
		}
		if (RMQ(st, N + 2, r, i - 1) < a[i]) l = r;
		llen = i - l;
		//cout << " "<< llen << endl;

		int I = N + 1 - i;
		l = 0, r = I - 1, m, v;
		//cerr << A[I] << endl;

		while (l + 1 < r) {
			m = (l + r) / 2;
			v = RMQ(ST, N + 2, m, I - 1);
			//cout << "Min[" << m << "," << (I-1) << "]=" << v << endl;
			if (v > A[I]) r = m;
			else          l = m;
		}
		if (RMQ(ST, N + 2, r, I - 1) < A[I]) l = r;
		rlen = I - l;
		//cout << " "<< rlen << endl;


		ret += a[i] * llen*rlen;
	}

	cout << ret << endl;

	return 0;
}



/*
2 1 3
1 1
1



0 1 3 2 4 0
 0 1 2 2 0
  0 1 2 0
   0 1 0
    0 0
     0
*/










Compiler output:
a.cc: In function 'int RMQUtil(int*, int, int, int, int, int)':
a.cc:143:24: error: 'INT_MAX' was not declared in this scope
  143 |                 return INT_MAX;
      |                        ^~~~~~~
a.cc:28:1: note: 'INT_MAX' is defined in header '<climits>'; this is probably fixable by adding '#include <climits>'
   27 | #include <assert.h>
  +++ |+#include <climits>
   28 |