#include using namespace std; #define ll long long const int N = 200005; const int mod = 1e9 + 7; inline int add(int x, int y){ x += y; if(x >= mod) x -= mod; return x;} inline int sub(int x, int y){ x -= y; if(x < 0) x += mod; return x;} inline int mul(int x, int y){ return (x * 1ll * y) % mod;} inline int powr(int a, ll b){ int x = 1 % mod; while(b){ if(b & 1) x = mul(x, a); a = mul(a, a); b >>= 1; } return x; } inline int inv(int a){ return powr(a, mod - 2);} const int inv2 = (mod + 1)/2; int l[N], r[N], A[N]; int pref[N]; int prefmax[N], suffmax[N], perm[N]; bool cmp(int i, int j){ return A[i] > A[j];} int sum(int i){ return ((i * 1ll * (i + 1)) / 2) % mod; } set added, st; map compress; int ulta[N]; const int M = N * 80; int lft[M], rgt[M], val[M]; int cnt; struct persistent_segtree{ int root[N]; persistent_segtree(){root[0] = 0;} void ADD(int v, int value, int rt, int newrt, int s = 0, int e = N){ val[newrt] = add(val[rt], value); if(s == e){ return; } int mid = (s + e) >> 1; if(v <= mid){ // right remains same rgt[newrt] = rgt[rt]; lft[newrt] = ++cnt; ADD(v, value, lft[rt], lft[newrt], s, mid); } else{ // left remains same lft[newrt] = lft[rt]; rgt[newrt] = ++cnt; ADD(v, value, rgt[rt], rgt[newrt], mid + 1, e); } } void ADD(int i, int v, int value){ root[i] = ++cnt; ADD(v, value, root[i - 1], root[i]); } int GET(int l, int r, int rt, int s = 0, int e = N){ if(!rt || l > e || s > r) return 0; if(s >= l && e <= r) return val[rt]; int mid = (s + e) >> 1; return add(GET(l, r, lft[rt], s, mid), GET(l, r, rgt[rt], mid + 1, e)); } int get(int l, int r, int x, int y){ if(l > r) return 0; return sub(GET(x, y, root[r]), GET(x, y, root[l - 1])); } void trace(int rt, int s = 1, int e = N){ if(!rt) return; int mid = (s + e) >> 1; trace(lft[rt], s, mid); trace(rgt[rt], mid + 1, e); } } tree1, tree2, tree3, tree4; int main(){ int n, mx = 0; cin >> n; for(int i = 1; i <= n; i++){ cin >> A[i]; mx = max(mx, A[i]); prefmax[i] = mx; perm[i] = i; st.insert(A[i]); } sort(perm + 1, perm + n + 1, cmp); added = {0, n + 1}; for(int i = 1; i <= n; i++){ int ind = perm[i]; auto it = added.upper_bound(ind); auto it2 = it; it--; l[ind] = ind - (*it) - 1; r[ind] = (*it2) - ind - 1; added.insert(ind); } for(int i = n; i >= 1; i--) suffmax[n - i + 1] = max(suffmax[n - i], A[i]); int ans = 0; for(int i = 1; i <= n; i++){ int x = add(1, mul(l[i] + r[i], inv2)); int y = mul(x, l[i] + 1); int cnt = mul(y, r[i] + 1); ans = add(ans, mul(A[i], cnt)); } for(int k = 1; k <= n; k++){ if(k > 2) ans = add(ans, mul(mx, mul(n - k + 1, pref[k - 2]))); pref[k] = add(pref[k - 1], n - k + 1); } int CNT = 0; for(int x : st) compress[x] = ++CNT, ulta[CNT] = x; for(int l2 = 1; l2 <= n; l2++){ tree1.ADD(l2, compress[prefmax[l2]], 1); tree2.ADD(l2, compress[prefmax[l2]], l2 - 1); tree3.ADD(l2, compress[prefmax[l2]], prefmax[l2]); tree4.ADD(l2, compress[prefmax[l2]], mul(l2 - 1, prefmax[l2])); } for(int l1 = 1; l1 <= n; l1++){ int MX = suffmax[l1]; if(l1 != n){ ans = add(ans, mul(mul(MX, l1), tree1.get(l1 + 1, n, 1, compress[MX] - 1))); ans = add(ans, mul(l1, tree3.get(l1 + 1, n, compress[MX], N))); } ans = add(ans, mul(MX, tree2.get(1, l1, 1, compress[MX] - 1))); ans = add(ans, tree4.get(1, l1, compress[MX], N)); } printf("%d\n", ans); }