#include <bits/stdc++.h>
const int MAXN = 1000005;
int n, k;
using namespace std;
struct Record {
  long long value, min_counter, max_counter;
} a[MAXN];
struct Node {
  int min_value, max_value;
} tree[MAXN << 2];
void build_tree(int left, int right, int x) {
  if (k == 0)
    tree[x].min_value = tree[x].max_value = 0;
  else
    tree[x].min_value = tree[x].max_value = n + 1;
  if (left == right) return;
  int mid = (left + right) / 2;
  build_tree(left, mid, ((x) << 1));
  build_tree(mid + 1, right, ((x) << 1 | 1));
}
void push_up(int x) {
  if (k == 0) {
    tree[x].min_value =
        max(tree[((x) << 1)].min_value, tree[((x) << 1 | 1)].min_value);
    tree[x].max_value =
        max(tree[((x) << 1)].max_value, tree[((x) << 1 | 1)].max_value);
  } else {
    tree[x].min_value =
        min(tree[((x) << 1)].min_value, tree[((x) << 1 | 1)].min_value);
    tree[x].max_value =
        min(tree[((x) << 1)].max_value, tree[((x) << 1 | 1)].max_value);
  }
}
void update(int pos, int value, int left, int right, int x) {
  if (left == right) {
    tree[x].min_value = tree[x].max_value = value;
    return;
  }
  int mid = (left + right) / 2;
  if (pos <= mid)
    update(pos, value, left, mid, ((x) << 1));
  else
    update(pos, value, mid + 1, right, ((x) << 1 | 1));
  push_up(x);
}
int query_min(int l, int r, int left, int right, int x) {
  if (l == left && r == right) return tree[x].min_value;
  int mid = (left + right) / 2;
  if (r <= mid)
    return query_min(l, r, left, mid, ((x) << 1));
  else if (l > mid)
    return query_min(l, r, mid + 1, right, ((x) << 1 | 1));
  else {
    if (k == 0)
      return max(query_min(l, mid, left, mid, ((x) << 1)),
                 query_min(mid + 1, r, mid + 1, right, ((x) << 1 | 1)));
    else
      return min(query_min(l, mid, left, mid, ((x) << 1)),
                 query_min(mid + 1, r, mid + 1, right, ((x) << 1 | 1)));
  }
}
int query_max(int l, int r, int left, int right, int x) {
  if (l == left && r == right) return tree[x].max_value;
  int mid = (left + right) / 2;
  if (r <= mid)
    return query_max(l, r, left, mid, ((x) << 1));
  else if (l > mid)
    return query_max(l, r, mid + 1, right, ((x) << 1 | 1));
  else {
    if (k == 0)
      return max(query_max(l, mid, left, mid, ((x) << 1)),
                 query_max(mid + 1, r, mid + 1, right, ((x) << 1 | 1)));
    else
      return min(query_max(l, mid, left, mid, ((x) << 1)),
                 query_max(mid + 1, r, mid + 1, right, ((x) << 1 | 1)));
  }
}
int main() {
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) {
    scanf("%lld", &a[i].value);
    a[i].min_counter = a[i].max_counter = 1;
  }
  build_tree(0, MAXN, 1);
  for (int i = 1; i <= n; i++) {
    a[i].min_counter *= (i - query_min(0, a[i].value, 0, MAXN, 1));
    a[i].max_counter *= (i - query_max(a[i].value, MAXN, 0, MAXN, 1));
    update(a[i].value, i, 0, MAXN, 1);
  }
  k = 1;
  build_tree(0, MAXN, 1);
  for (int i = n; i > 0; i--) {
    a[i].min_counter *= (query_min(0, a[i].value - 1, 0, MAXN, 1) - i);
    a[i].max_counter *= (query_max(a[i].value + 1, MAXN, 0, MAXN, 1) - i);
    update(a[i].value, i, 0, MAXN, 1);
  }
  long long ans = 0;
  for (int i = 1; i <= n; i++) {
    ans += a[i].value * (a[i].max_counter - a[i].min_counter);
  }
  printf("%lld", ans);
  return 0;
}
