#include #include #include #include #include #include using namespace std; #define M 1000000007LL struct llnode { int64_t previd; int64_t nextid; int64_t val; int64_t tetwidth; int64_t contains; bool visited = false; }; vector lst(200002); int64_t ans = 0; int64_t rectsofar = 0; int64_t FF(int64_t x) { return x * (x + 2LL) * (2LL*x+2LL); } int64_t tet(int64_t x) { return ((x * (x+1LL) * (x+2LL))/6LL) % M; } int64_t tri(int64_t x) { return ((((x+1LL)*x) % M)*((M+1LL)/2LL)) % M; } int64_t rectthingy(int64_t x, int64_t y) { int64_t a = x + y; int64_t d = x - y; if (d < 0) d = -d; return (FF(a) - FF(d) - (min(x,y) * (d * d) * 12LL)) / 48LL; } vector slowgen(vector A) { vector B; int64_t offset = 0; for (int64_t i = 0; i < A.size(); i++) B.push_back(A[i]); for (int64_t k = 1; k < A.size(); k++) { for (int64_t i = 0; i < A.size() - k; i++) { B.push_back(max(B[offset + i], B[offset + i + 1])); } offset += (A.size() - k + 1); } return B; } int main() { /* Enter your code here. Read input from STDIN. Print output to STDOUT */ int64_t n, a; ans = 0; cin >> n; lst[0].previd = 0; lst[0].val = -1; lst[0].tetwidth = -1; lst[0].nextid = 1; vector> locs(1000001); int64_t mx = 0; vector A; for (int64_t i = 1; i <= n; i++) { lst[i].previd = i-1; lst[i].nextid = i+1; lst[i].tetwidth = 1; lst[i].contains = 0; lst[i].visited = false; //lst[i].val = (i*i*i + 48*i + 10000); cin >> lst[i].val; A.push_back(lst[i].val); mx = max(mx, lst[i].val); locs[lst[i].val].push_back(i); } /* auto B = slowgen(A); auto C = slowgen(B); for (int64_t c : A) cout << c << " "; cout << endl; cout << C.size() << endl; for (int64_t c: C) ans = (ans + c) %M; cout << ans << endl; ans = 0; */ lst[n+1].previd = n; lst[n+1].nextid = n+1; lst[n+1].val = -1; lst[n+1].tetwidth = -1; // Go in increasing order for (int64_t i = 1; i < mx; i++) { int64_t leftextent = 0; int64_t rightextent = 0; for (int64_t j : locs[i]) { if (lst[j].visited) continue; int64_t nextnode = j; int64_t ctns = 0; // Start going left while (true) { nextnode = lst[nextnode].previd; if (nextnode == 0) break; if (lst[nextnode].val <= i) { lst[j].previd = lst[nextnode].previd; lst[lst[j].previd].nextid = j; lst[j].tetwidth += lst[nextnode].tetwidth; ctns += lst[nextnode].contains; ctns %= M; lst[nextnode].visited = true; } else { break; } } // Start going right. nextnode = j; while (true) { nextnode = lst[nextnode].nextid; if (nextnode == n+1) break; if (lst[nextnode].val <= i) { lst[j].nextid = lst[nextnode].nextid; lst[lst[j].nextid].previd = j; lst[j].tetwidth += lst[nextnode].tetwidth; ctns += lst[nextnode].contains; ctns %= M; lst[nextnode].visited = true; } else { break; } } // Calculate my contents int64_t basecontents = tet(lst[j].tetwidth); lst[j].contains = basecontents; int64_t tosub = basecontents - ctns; if (tosub < 0) tosub = M + tosub; ans = (ans + tosub * i) % M; //cout << i << " " << j << " " << ans << endl; } if (lst[lst[0].nextid].val == i || lst[lst[n+1].previd].val == i) { int64_t ni = 0; while (ni != n+1 && lst[lst[ni].nextid].val <= i) { leftextent += lst[lst[ni].nextid].tetwidth - 1LL; ni = lst[ni].nextid; } ni = n+1; while (ni != 0 && lst[lst[ni].previd].val <= i) { rightextent += lst[lst[ni].previd].tetwidth; ni = lst[ni].previd; } int64_t rect = rectthingy(leftextent, rightextent); if (1) { //cout << i << " " << rect << endl; ans = (ans + ((rect - rectsofar)%M) * i) % M; rectsofar = max(rectsofar, rect); } } } int64_t torem = rectsofar; int64_t nn = lst[0].nextid; while (nn != n + 1) { //cerr << nn << endl; if (lst[nn].val < mx) torem = (torem + lst[nn].contains) % M; nn = lst[nn].nextid; } int64_t base = tri(tri(n)%M)%M; //cerr << base << endl; //cerr << torem << endl; base = (base - torem) % M; //cerr << base << endl; base = (M + base) % M; ans = (ans + base * mx) % M; cout << ans << endl; return 0; }