#include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; const int SIZE = 1 << 10; int pointer = SIZE; char buffer[SIZE]; char Advance() { if (pointer == SIZE) { fread(buffer, 1, SIZE, stdin); pointer = 0; } return buffer[pointer++]; } int Read() { int answer = 0; char ch = Advance(); while (!isdigit(ch)) ch = Advance(); while (isdigit(ch)) { answer = answer * 10 + ch - '0'; ch = Advance(); } return answer; } const int MAXN = 200000; const int MAXNODES = 524288; const int MOD = 1000000007; void Add(int &x, int y) { x += y; if (x >= MOD) x -= MOD; } void Subtract(int &x, int y) { x -= y; if (x < 0) x += MOD; } int RaiseToPower(int base, int power) { int answer = 1; while (power) { if (power % 2) answer = (1LL * answer * base) % MOD; base = (1LL * base * base) % MOD; power /= 2; } return answer; } int v[1 + MAXN]; pair vn[1 + MAXN]; vector here[1 + MAXN]; int n, tree[1 + MAXNODES], value[1 + MAXN], answer = 0; void Normalize(int &m) { for (int i = 1; i <= n; i++) vn[i] = make_pair(v[i], i); sort(vn + 1, vn + n + 1); m = 0; for (int i = 1; i <= n; i++) { if (vn[i].first != vn[i - 1].first) { m++; value[m] = vn[i].first; } v[vn[i].second] = m; here[m].push_back(vn[i].second); } } void BuildTree(int node, int left, int right) { if (left == right) { tree[node] = v[left]; return; } int middle = (left + right) / 2; BuildTree(2 * node, left, middle); BuildTree(2 * node + 1, middle + 1, right); tree[node] = max(tree[2 * node], tree[2 * node + 1]); } int Query(int node, int left, int right, int from, int to) { if (from <= left && right <= to) return tree[node]; int middle = (left + right) / 2, answer = 0; if (from <= middle) answer = max(answer, Query(2 * node, left, middle, from, to)); if (middle + 1 <= to) answer = max(answer, Query(2 * node + 1, middle + 1, right, from, to)); return answer; } int BinarySearch(int x, int limit) { int left = 0, right = here[x].size() - 1, best = here[x].size(); while (left <= right) { int middle = (left + right) / 2; if (here[x][middle] >= limit) { best = middle; right = middle - 1; } else left = middle + 1; } return best; } int Normal(int left, int right) { int l = right - left + 1, x = Query(1, 1, n, left, right), a = BinarySearch(x, left), b = BinarySearch(x, right + 1) - 1; int total = (1LL * l * (l + 1) * (l + 2) / 6) % MOD; if (b - a + 1 == right - left + 1) answer = (1LL * total * value[x]+ answer) % MOD; else { int now = total; if (here[x][a] != left) Subtract(now, Normal(left, here[x][a] - 1)); for (int i = a; i < b; i++) if (here[x][i] <= here[x][i + 1] - 2) Subtract(now, Normal(here[x][i] + 1, here[x][i + 1] - 1)); if (here[x][b] != right) Subtract(now, Normal(here[x][b] + 1, right)); answer = (1LL * now * value[x] + answer) % MOD; } return total; } int Special(int left, int right) { int x = max(Query(1, 1, n, 1, left), Query(1, 1, n, right, n)), l2 = left, l1 = n - right + 1, k = min(l2 - 1, l1); int a = BinarySearch(x, left + 1) - 1, b = BinarySearch(x, right); int total = (1LL * l1 * (l1 + 1) * (l1 + 2) / 6 + 1LL * l2 * (l2 + 1) * (l2 + 2) / 6) % MOD; total = (1LL * k * l1 * l2 + total) % MOD; Subtract(total, (1LL * k * (k + 1) * l1 / 2) % MOD); Subtract(total, (1LL * (k - 1) * k * l2 / 2) % MOD); total = (1LL * (k - 1) * k * (k + 1) / 3 + total) % MOD; if (a + 1 + here[x].size() - b == l1 + l2) answer = (1LL * total * value[x] + answer) % MOD; else { int now = total; if (a == -1) { if (here[x].back() == n) Subtract(now, Normal(1, left)); else Subtract(now, Special(left, here[x].back() + 1)); if (here[x][b] != right) Subtract(now, Normal(right, here[x][b] - 1)); for (int i = b; i < here[x].size() - 1; i++) if (here[x][i] <= here[x][i + 1] - 2) Subtract(now, Normal(here[x][i] + 1, here[x][i + 1] - 1)); } else if (b == here[x].size()) { if (here[x][0] == 1) Subtract(now, Normal(right, n)); else Subtract(now, Special(here[x][0] - 1, right)); if (here[x][a] != left) Subtract(now, Normal(here[x][a] + 1, left)); for (int i = 0; i < a; i++) if (here[x][i] <= here[x][i + 1] - 2) Subtract(now, Normal(here[x][i] + 1, here[x][i + 1] - 1)); } else { if (here[x][0] != 1 && here[x].back() != n) Subtract(now, Special(here[x][0] - 1, here[x].back() + 1)); else { if (here[x][0] != 1) Subtract(now, Normal(1, here[x][0] - 1)); if (here[x].back() != n) Subtract(now, Normal(here[x].back() + 1, n)); } if (here[x][a] != left) Subtract(now, Normal(here[x][a] + 1, left)); for (int i = 0; i < a; i++) if (here[x][i] <= here[x][i + 1] - 2) Subtract(now, Normal(here[x][i] + 1, here[x][i + 1] - 1)); if (here[x][b] != right) Subtract(now, Normal(right, here[x][b] - 1)); for (int i = b; i < here[x].size() - 1; i++) if (here[x][i] <= here[x][i + 1] - 2) Subtract(now, Normal(here[x][i] + 1, here[x][i + 1] - 1)); } answer = (1LL * now * value[x] + answer) % MOD; } return total; } int main() { //freopen("tema.in", "r", stdin); //freopen("tema.out", "w", stdout); scanf("%d", &n); int m; for (int i = 1; i <= n; i++) scanf("%d", &v[i]); Normalize(m); BuildTree(1, 1, n); int total = (1LL * n * (n + 1) / 2) % MOD; total = (1LL * total * (total + 1) / 2) % MOD; for (int i = 0; i < here[m].size() - 1; i++) if (here[m][i] <= here[m][i + 1] - 2) Subtract(total, Normal(here[m][i] + 1, here[m][i + 1] - 1)); if (here[m][0] != 1 && here[m].back() != n) Subtract(total, Special(here[m][0] - 1, here[m].back() + 1)); else { if (here[m][0] != 1) Subtract(total, Normal(1, here[m][0] - 1)); if (here[m].back() != n) Subtract(total, Normal(here[m].back() + 1, n)); } answer = (1LL * total * value[m] + answer) % MOD; printf("%d\n", answer); return 0; }