#define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #pragma comment (linker, "/STACK:256000000") #pragma GCC optimize("Ofast") #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") using namespace std; vector < int > merge(vector < int > a, vector < int > b) { for (int i = 0; i < b.size(); ++i) { a.push_back(b[i]); } sort(a.begin(), a.end()); a.resize(unique(a.begin(), a.end()) - a.begin()); return a; } vector < vector < int > > step(vector < vector < int > > a) { vector < vector < int > > res; for (int len = 1; len <= a.size(); ++len) { for (int i = 0; i + len - 1 < a.size(); ++i) { vector < int > cur; for (int j = i; j < i + len; ++j) { cur = merge(cur, a[j]); } res.push_back(cur); } } return res; } const long long P = 1000000007; const int maxN = 210000; int n; int a[maxN]; void computeFirst(long long &ans, long long &total, int n) { set < pair < int, long long > > c, d; c.insert(make_pair(a[n - 1], 1)); long long sc = a[n - 1]; d.insert(make_pair(a[n - 1], 1)); long long sd = a[n - 1]; int oldtotal = total; int oldans = ans; total = (total + 1) % P; ans = (ans + a[n - 1]) % P; long long s = 1; int shift = 0; for (int i = n - 2; i >= 1; --i) { ++shift; s += (shift + 1); s %= P; total = (total + s) % P; { long long cnt = 0; while (!d.empty() && d.begin()->first <= a[i]) { cnt = (cnt + d.begin()->second) % P; sd -= (long long)(d.begin()->first) * d.begin()->second; sd %= P; d.erase(d.begin()); } cnt = (cnt + 1 - shift) % P; d.insert(make_pair(a[i], cnt)); sd += cnt * (long long)(a[i]); sd %= P; } { long long cnt = 0; while (!c.empty() && c.begin()->first <= a[i]) { cnt = (cnt + c.begin()->second) % P; sc -= (long long)(c.begin()->first) * c.begin()->second; sc %= P; c.erase(c.begin()); } cnt = (cnt + 1) % P; c.insert(make_pair(a[i], cnt)); sc += cnt * (long long)(a[i]); sc %= P; } ans = (ans + sd + (long long)(shift) * sc) % P; } } void computeSecond(long long &ans, long long &total, int n) { vector < int > buf; int res = 0; int value = 0; for (int i = 0; i + 1 < n; ++i) { //buf.push_back(i); value = max(value, a[i]); ++res; //M[buf] = res; ans = (ans + (long long)(value) * (long long)(res)) % P; total = (total + res) % P; } } void output(multiset < pair < int, long long > > s) { cout << "====" << endl; while (!s.empty()) { cout << s.begin()->first << ": " << s.begin()->second << endl; s.erase(s.begin()); } cout << "----" << endl; } void prepare(multiset < pair < int, long long > > s) { while (!s.empty()) { if (s.begin()->second == 0) { s.erase(s.begin()); } else { break; } } } void computeThird(long long &ans, long long &total, int n) { if (n < 4) { return; } int oldans = ans; int oldtotal = total; /*for (int missing = n - 2; missing > 1; --missing) { int value = 0; for (int i = 0; i < missing; ++i) { value = max(value, a[i]); } int res = 0; for (int i = n - 1; i > missing; --i) { value = max(value, a[i]); ++res; int cnt = min(missing - 1, res); if (cnt > 0) { ans = (ans + (long long)(value) * (long long)(cnt)) % P; total = (total + cnt) % P; } } }*/ int gmax = 0; for (int i = 0; i < n; ++i) { gmax = max(gmax, a[i]); } multiset < pair < int, long long > > b, c, d; long long sd = 0, sc = 0, sb = 0; long long td = 0, tc = 0, tb = 0; int value = max(a[0], a[1]); int cnt = 0; for (int i = n - 1; i > 2; --i) { value = max(value, a[i]); d.insert(make_pair(value, 1)); sd = (sd + value) % P; total = (total + 1) % P; td = (td + 1) % P; ++cnt; c.insert(make_pair(value, cnt)); sc = (sc + (long long)(value) * (long long)(cnt)) % P; tc = (tc + cnt) % P; if (cnt - 1 > 0) { b.insert(make_pair(value, cnt - 1)); sb = (sb + (long long)(value) * (long long)(cnt - 1)) % P; tb = (tb + cnt - 1) % P; } } ans = (ans + sd) % P; int tvalue = max(a[n - 1], a[0]); tvalue = max(a[0], a[1]); int bound = n - 2; long long cbound = -1; for (int missing = 3; missing <= n - 2; ++missing) { tvalue = max(tvalue, a[missing - 1]); --bound; ++cbound; //output(d); //cerr << sc << " " << sb << " " << sd << endl; //cerr << tc << " " << tb << " " << td << endl; { long long cnt = 0; while (!d.empty() && d.begin()->first <= a[missing - 1]) { cnt = (cnt + d.begin()->second); sd -= (long long)(d.begin()->first) * d.begin()->second; sd %= P; d.erase(d.begin()); } if (cnt > 0) { d.insert(make_pair(a[missing - 1], cnt)); sd += (cnt % P) * (long long)(a[missing - 1]); sd %= P; } } if (!d.empty()) { pair < int, long long > p = *d.rbegin(); d.erase(d.find(p)); if (p.second > 1) { d.insert(make_pair(p.first, p.second - 1)); } sd -= p.first; sd %= P; td = (td - 1) % P; if (!d.empty()) { p = *d.begin(); d.erase(d.begin()); if (p.second > 1) { d.insert(make_pair(p.first, p.second - 1)); } sd -= p.first; sd %= P; td = (td - 1) % P; } } { long long cnt = 0; while (!c.empty() && c.begin()->first <= a[missing - 1]) { cnt = (cnt + c.begin()->second); sc -= (long long)(c.begin()->first) * c.begin()->second; sc %= P; c.erase(c.begin()); } if (cnt > 0) { c.insert(make_pair(a[missing - 1], cnt)); sc += (cnt % P) * (long long)(a[missing - 1]); sc %= P; } } if (!c.empty()) { pair < int, long long > p = *c.rbegin(); //cerr << "x: " << p.first << " " << p.second << " " << bound << endl; c.erase(c.find(p)); if (p.second > bound) { c.insert(make_pair(p.first, p.second - bound)); } sc -= (long long)(p.first) * (long long)(bound); sc %= P; tc = (tc - bound) % P; } { long long cnt = 0; while (!b.empty() && b.begin()->first <= a[missing - 1]) { cnt = (cnt + b.begin()->second); sb -= (long long)(b.begin()->first) * b.begin()->second; sb %= P; b.erase(b.begin()); } if (cnt > 0) { b.insert(make_pair(a[missing - 1], cnt)); sb += (cnt % P) * (long long)(a[missing - 1]); sb %= P; } } if (!b.empty()) { pair < int, long long > p = *b.rbegin(); b.erase(b.find(p)); //cerr << "b: " << p.first << " " << p.second << " " << bound - 1 << endl; if (p.second > bound - 1) { b.insert(make_pair(p.first, p.second + 1 - bound)); } sb -= (long long)(p.first) * (long long)(bound - 1); sb %= P; tb = (tb - bound + 1) % P; tb %= P; if (!b.empty() && cbound > 0) { p = *b.begin(); b.erase(b.begin()); if (p.second > cbound) { b.insert(make_pair(p.first, p.second - cbound)); } sb -= (long long)(p.first) * (long long)(cbound); sb %= P; tb = (tb - cbound) % P; } } //prepare(c); //prepare(b); //prepare(d); //output(c); //output(b); //output(d); //cerr << sc << " " << sb << " " << sd << endl; //cerr << tc << " " << tb << " " << td << endl; //cerr << tc - tb + (cbound + 1) * td << endl; ans = (ans + sc - sb + (cbound + 1) * sd) % P; total = (total + tc - tb + (cbound + 1) * td) % P; } //cerr << "o: " << ans - oldans << " " << total - oldtotal << endl; } void generate(long long &ans, int n) { long long total = 0; computeFirst(ans, total, n); computeSecond(ans, total, n); computeThird(ans, total, n); long long x = (long long)(n) * (long long)(n + 1) / 2LL; x %= P; x = (x * (x + 1)) % P; x = (x * (P + 1)) / 2LL; x %= P; int value = 0; for (int i = 0; i < n; ++i) { value = max(value, a[i]); } ans = (ans + (long long)(value) * (long long)(x - total)) % P; ans = (ans + P) % P; } long long trivial() { vector < int > b; for (int i = 1; i <= n; ++i) { for (int j = 0; j + i - 1 < n; ++j) { int value = 0; for (int k = j; k < j + i; ++k) { value = max(value, a[k]); } b.push_back(value); } } int n = b.size(); int res = 0; for (int i = 1; i <= n; ++i) { for (int j = 0; j + i - 1 < n; ++j) { int value = 0; for (int k = j; k < j + i; ++k) { value = max(value, b[k]); } res += value; res %= P; } } return res; } int main() { //freopen("input.txt", "r", stdin); //freopen("output.txt", "w", stdout); /*while (true) { n = 20; for (int i = 0; i < n; ++i) { a[i] = rand() % 10 + 1; } long long res = 0; generate(res, n); if (trivial() != res) { cerr << "bad" << endl; cerr << res << endl; cerr << trivial() << endl; cerr << n << endl; for (int i = 0; i < n; ++i) { cerr << a[i] << " "; } cerr << endl; return 0; } cerr << "test" << endl; }*/ scanf("%d", &n); for (int i = 0; i < n; ++i) { scanf("%d", &a[i]); } long long res = 0; generate(res, n); cout << res << endl; //cout << trivial() << endl; /*vector < vector < int > > a; int n; cin >> n; for (int i = 0; i < n; ++i) { a.push_back(vector < int > (1, i)); } a = step(a); a = step(a); map < vector < int >, int > cnt; for (int i = 0; i < a.size(); ++i) { ++cnt[a[i]]; } map < vector < int >, int > A = generate(n); int tot = 0; for (map < vector < int >, int > ::iterator it = cnt.begin(); it != cnt.end(); ++it) { tot += it->second; if (A[it->first] != it->second) { for (int i = 0; i < it->first.size(); ++i) { cout << it->first[i] << ","; } cout << ": " << it->second << " " << A[it->first] << endl; } A.erase(it->first); } int m = n * (n + 1) / 2; m = m * (m + 1) / 2; cerr << "tot:" << tot << " " << m << endl; cerr << "remained: " << A.size() << endl; for (map < vector < int >, int > ::iterator it = A.begin(); it != A.end(); ++it) { for (int i = 0; i < it->first.size(); ++i) { cout << it->first[i] << ","; } cout << ": " << it->second << " " << cnt[it->first] << endl; }*/ return 0; }