#include using namespace std; typedef long long ll; struct Line { ll m, b; Line(ll m, ll b) : m(m), b(b) {} ll eval(ll x) const { return m * x + b; } }; class LiChaoTree { struct Node { Line line; Node* left; Node* right; Node(Line line) : line(line), left(nullptr), right(nullptr) {} }; Node* root; const ll L, R; public: LiChaoTree(ll l, ll r) : L(l), R(r), root(nullptr) {} void insert(Line new_line) { if (!root) { root = new Node(new_line); return; } Node* cur = root; ll l_current = L, r_current = R; while (true) { ll m = (l_current + r_current) >> 1; bool left_new = new_line.eval(l_current) > cur->line.eval(l_current); bool mid_new = new_line.eval(m) > cur->line.eval(m); bool right_new = new_line.eval(r_current) > cur->line.eval(r_current); if (mid_new) { swap(cur->line, new_line); } if (l_current == r_current) { break; } if (left_new != mid_new) { if (!cur->left) { cur->left = new Node(new_line); break; } cur = cur->left; r_current = m; } else if (right_new != mid_new) { if (!cur->right) { cur->right = new Node(new_line); break; } cur = cur->right; l_current = m + 1; } else { break; } } } ll query(ll x) { if (!root) return LLONG_MIN; ll res = LLONG_MIN; Node* cur = root; ll l = L, r = R; while (true) { res = max(res, cur->line.eval(x)); ll m = (l + r) >> 1; if (x <= m) { if (cur->left) { cur = cur->left; r = m; } else { break; } } else { if (cur->right) { cur = cur->right; l = m + 1; } else { break; } } } return res; } }; int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); int N; cin >> N; vector Q(N); for (int i = 0; i < N; ++i) { cin >> Q[i]; } LiChaoTree tree(-1'000'000'000'000'000, 1'000'000'000'000'000); tree.insert(Line(Q[0], 0)); ll max_ans = LLONG_MIN; for (int i = 1; i < N; ++i) { ll x = Q[i]; ll current = tree.query(x); if (current > max_ans) { max_ans = current; } tree.insert(Line(Q[i], current)); } cout << max_ans << endl; return 0; }