// __author__ HD #include #define endl '\n' #define MAX 100005 #define MOD 1000000000 using namespace std; typedef long long ll; class SegmentTree { private: vector st, A, lazy; int n; int left(int p) { return p << 1; } int right(int p) { return (p << 1) + 1; } void build(int p, int L, int R) { if (L == R) st[p] = A[L]; else { build(left(p), L, (L + R) / 2); build(right(p), (L + R) / 2 + 1, R); ll p1 = st[left(p)]; ll p2 = st[right(p)]; st[p] = max(p1, p2); // Lineas que varian en dependencia del problema. } } ll query(int p, int L, int R, int i, int j) { if (L > R) return 0; // Retornar en dependencia del tipo de vi. if (lazy[p] != 0ll) { // Valor que indica si se ha realizado una actualización a este nodo. st[p] += lazy[p]; if (L != R) { lazy[left(p)] += lazy[p]; lazy[right(p)] += lazy[p]; } lazy[p] = 0ll; } if (i > R || j < L) return 0; if (L >= i && R <= j) return st[p]; ll p1 = query(left(p), L, (L + R) / 2, i, j); ll p2 = query(right(p), (L + R) / 2 + 1, R, i, j); //if (p1 == -1ll) return p2; //Comparar con el valor que devuelve la primera linea de este método. //if (p2 == -1ll) return p1; //Idem. return max(p1, p2); // Líneas que varian en dependencia del problema. } ll upd(int p, int L, int R, int i, ll value) { if (i > R || i < L) return st[p]; else if (L != R) { ll p1 = upd(left(p), L, (L + R) / 2, i, value); ll p2 = upd(right(p), (L + R) / 2 + 1, R, i, value); st[p] = (p1 + p2) % MOD; } else st[p] = value; return st[p]; } void lazyUpd(int p, int L, int R, int i, int j, ll value) { if (L > R) return; if (lazy[p] != 0ll) { // This node needs to be updated st[p] += lazy[p]; // Update it if (L != R) { lazy[left(p)] += lazy[p]; // Mark child as lazy lazy[right(p)] += lazy[p]; // Mark child as lazy } lazy[p] = 0ll; // Reset it } if (L > j || R < i) // Current segment is not within range [i, j] return; if (L >= i && R <= j) { // Segment is fully within range st[p] += value; if (L != R) { // Not leaf node lazy[left(p)] += value; lazy[right(p)] += value; } return; } lazyUpd(left(p), L, (L + R) / 2, i, j, value); // Updating left child lazyUpd(right(p), (L + R) / 2 + 1, R, i, j, value); // Updating right child st[p] = st[left(p)] + st[right(p)]; } public: SegmentTree(const vector &_A) { A = _A; n = (int) A.size(); st.assign(4 * n, 0ll); lazy.assign(4 * n, 0ll); build(1, 0, n - 1); } ll query(int i, int j) { return query(1, 0, n - 1, i, j); } void upd(int i, ll value) { upd(1, 0, n - 1, i, value); A[i] = value; } void lazyUpd(int i, int j, ll value) { lazyUpd(1, 0, n - 1, i, j, value); } }; int main() { ios_base::sync_with_stdio(0); cin.tie(0); int n; cin >> n; vector A(n); for (int i = 0; i < n; ++i) { cin >> A[i]; } SegmentTree st = SegmentTree(A); vector b; for (int k = 0; k <= A.size() - 1; ++k) { for (int i = 0; i <= A.size() - k - 1; ++i) { int j = i + k; b.push_back(st.query(i, j)); } } st = SegmentTree(b); ll answer = 0ll; for (int k = 0; k <= b.size() - 1; ++k) { for (int i = 0; i <= b.size() - k - 1; ++i) { int j = i + k; answer += st.query(i, j); } } cout << answer << endl; return 0; }