import java.io.OutputStream; import java.io.IOException; import java.io.InputStream; import java.util.SortedSet; import java.util.InputMismatchException; import java.util.Random; import java.util.ArrayList; import java.io.OutputStreamWriter; import java.util.NoSuchElementException; import java.io.OutputStream; import java.io.PrintWriter; import java.util.Iterator; import java.io.BufferedWriter; import java.util.Collection; import java.util.Set; import java.util.NavigableSet; import java.io.IOException; import java.util.List; import java.io.Writer; import java.util.Comparator; import java.util.Collections; import java.io.InputStream; /** * Built using CHelper plug-in * Actual solution is at the top * * @author Egor Kulikov (egor@egork.net) */ public class Solution { public static void main(String[] args) { InputStream inputStream = System.in; OutputStream outputStream = System.out; InputReader in = new InputReader(inputStream); OutputWriter out = new OutputWriter(outputStream); PairSums solver = new PairSums(); solver.solve(1, in, out); out.close(); } static class PairSums { public void solve(int testNumber, InputReader in, OutputWriter out) { int n = in.readInt(); int[] a = in.readIntArray(n); /* long aa = 0; int f = 0; int t = 0; for (int i = 0; i < n; i++) { long sum = 0; long add = 0; for (int j = i; j < n; j++) { add += sum * a[j]; sum += a[j]; if (add > aa) { f = i; t = j; aa = add; } } } System.err.println(f + " " + t + " " + aa);*/ long[] k = new long[n + 1]; long[] b = new long[n + 1]; TreapSet set = new TreapSet<>((x, y) -> k[x] == k[y] ? x - y : Long.compare(k[y], k[x])); set.add(n); long answer = 0; long sum = 0; long add = 0; long sumSq = 0; for (int i = 0; i < n; i++) { add += sum * a[i]; sum += a[i]; sumSq += a[i] * a[i]; int left = 0; int right = set.size() - 1; while (right - left >= 3) { int lm = (2 * left + right) / 3; int rm = (2 * right + left) / 3; int lmi = set.get(lm); int rmi = set.get(rm); long vl = k[lmi] * sum + b[lmi]; long vr = k[rmi] * sum + b[rmi]; if (vl < vr) { right = rm; } else { left = lm; } } for (int j = left; j <= right; j++) { int id = set.get(j); answer = Math.max(answer, add - sum * k[id] - b[id]); } k[i] = sum; b[i] = -add - sumSq; Integer l = set.floor(i); Integer r = set.ceiling(i); if (l != null && k[l] == k[i]) { if (b[l] <= b[i]) { continue; } else { set.remove(l); set.add(i); l = set.floor(i); } } else if (l == null || r == null) { set.add(i); } else { boolean need = isNeed(k, b, i, l, r); if (need) { set.add(i); } else { continue; } } while (l != null) { Integer ll = set.lower(l); if (ll == null) { break; } if (isNeed(k, b, l, ll, i)) { break; } else { set.remove(l); l = ll; } } while (r != null) { Integer rr = set.higher(r); if (rr == null) { break; } if (isNeed(k, b, r, i, rr)) { break; } else { set.remove(r); r = rr; } } } out.printLine(answer); } protected boolean isNeed(long[] k, long[] b, int i, int l, int r) { long db = b[r] - b[l]; long dk = k[l] - k[r]; if (dk < 0) { db = -db; dk = -dk; } long our = k[i] * db + b[i] * dk; long was = k[l] * db + b[l] * dk; return our < was; } } static class InputReader { private InputStream stream; private byte[] buf = new byte[1024]; private int curChar; private int numChars; private InputReader.SpaceCharFilter filter; public InputReader(InputStream stream) { this.stream = stream; } public int[] readIntArray(int size) { int[] array = new int[size]; for (int i = 0; i < size; i++) { array[i] = readInt(); } return array; } public int read() { if (numChars == -1) { throw new InputMismatchException(); } if (curChar >= numChars) { curChar = 0; try { numChars = stream.read(buf); } catch (IOException e) { throw new InputMismatchException(); } if (numChars <= 0) { return -1; } } return buf[curChar++]; } public int readInt() { int c = read(); while (isSpaceChar(c)) { c = read(); } int sgn = 1; if (c == '-') { sgn = -1; c = read(); } int res = 0; do { if (c < '0' || c > '9') { throw new InputMismatchException(); } res *= 10; res += c - '0'; c = read(); } while (!isSpaceChar(c)); return res * sgn; } public boolean isSpaceChar(int c) { if (filter != null) { return filter.isSpaceChar(c); } return isWhitespace(c); } public static boolean isWhitespace(int c) { return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1; } public interface SpaceCharFilter { public boolean isSpaceChar(int ch); } } static class TreapSet implements NavigableSet { protected static final Random rnd = new Random(239); protected final Node nullNode; protected final Comparator comparator; protected Node root; private final K from; private final K to; private final boolean fromInclusive; private final boolean toInclusive; public TreapSet() { this((Comparator) null); } public TreapSet(Comparator comparator) { this(null, null, false, false, comparator, null, null); } public TreapSet(Iterable collection) { this(collection, null); } public TreapSet(Iterable collection, Comparator comparator) { this(comparator); addAll(collection); } protected TreapSet(K from, K to, boolean fromInclusive, boolean toInclusive, Comparator comparator, Node root, Node nullNode) { this.comparator = comparator; this.from = from; this.to = to; this.fromInclusive = fromInclusive; this.toInclusive = toInclusive; if (nullNode == null) { nullNode = new NullNode(); } if (root == null) { root = nullNode; } this.root = root; this.nullNode = nullNode; } public boolean addAll(Iterable collection) { boolean result = false; for (K element : collection) { result |= add(element); } return result; } public K lower(K k) { Node target = root.lower(k); if (target == nullNode) { return null; } if (belongs(target.key)) { return target.key; } return null; } private boolean belongs(K key) { int valueFrom = compare(from, key); int valueTo = compare(key, to); return (valueFrom < 0 || valueFrom == 0 && fromInclusive) && (valueTo < 0 || valueTo == 0 && toInclusive); } public K floor(K k) { Node target = root.floor(k); if (target == nullNode) { return null; } if (belongs(target.key)) { return target.key; } return null; } public K ceiling(K k) { Node target = root.ceil(k); if (target == nullNode) { return null; } if (belongs(target.key)) { return target.key; } return null; } public K higher(K k) { Node target = root.higher(k); if (target == nullNode) { return null; } if (belongs(target.key)) { return target.key; } return null; } public K pollFirst() { K first = first(); if (first == null) { throw new NoSuchElementException(); } root.erase(first); return first; } public K pollLast() { K last = last(); if (last == null) { throw new NoSuchElementException(); } root.erase(last); return last; } public int size() { if (from == null && to == null) { return root.size; } if (from == null) { Node to = toInclusive ? root.floor(this.to) : root.lower(this.to); if (to == nullNode) { return 0; } return root.indexOf(to) + 1; } if (to == null) { Node from = fromInclusive ? root.ceil(this.from) : root.higher(this.from); if (from == nullNode) { return 0; } return root.size - root.indexOf(from); } Node from = fromInclusive ? root.ceil(this.from) : root.higher(this.from); if (from == nullNode || !belongs(from.key)) { return 0; } Node to = toInclusive ? root.floor(this.to) : root.lower(this.to); return root.indexOf(to) - root.indexOf(from) + 1; } public boolean isEmpty() { return size() == 0; } @SuppressWarnings({"unchecked"}) public boolean contains(Object o) { return belongs((K) o) && root.search((K) o) != nullNode; } public Iterator iterator() { return new Iterator() { private K current = first(); public boolean hasNext() { return current != null; } public K next() { K result = current; current = higher(current); return result; } public void remove() { TreapSet.this.remove(current); } }; } public Object[] toArray() { Object[] array = new Object[size()]; int index = 0; for (K key : this) { array[index++] = key; } return array; } @SuppressWarnings({"unchecked"}) public T[] toArray(T[] a) { if (a.length < size()) { throw new IllegalArgumentException(); } int index = 0; for (K key : this) { a[index++] = (T) key; } return a; } public boolean add(K k) { if (k == null) { throw new NullPointerException(); } if (contains(k)) { return false; } root = root.insert(createNode(k)); return true; } protected Node createNode(K k) { return new Node(k, rnd.nextLong()); } public boolean remove(Object o) { if (!contains(o)) { return false; } //noinspection unchecked root = root.erase((K) o); return true; } public boolean containsAll(Collection c) { for (Object o : c) { if (!contains(o)) { return false; } } return true; } public boolean addAll(Collection c) { return addAll((Iterable) c); } public boolean retainAll(Collection c) { List toRemove = new ArrayList(); for (K key : this) { if (!c.contains(key)) { toRemove.add(key); } } return removeAll(toRemove); } public boolean removeAll(Collection c) { boolean result = false; for (Object o : c) { result |= remove(o); } return result; } public void clear() { retainAll(Collections.emptySet()); } public NavigableSet descendingSet() { throw new UnsupportedOperationException(); } public Iterator descendingIterator() { return new Iterator() { private K current = last(); public boolean hasNext() { return current != null; } public K next() { K result = current; current = lower(current); return result; } public void remove() { TreapSet.this.remove(current); } }; } public NavigableSet subSet(K fromElement, boolean fromInclusive, K toElement, boolean toInclusive) { return new TreapSet(fromElement, toElement, fromInclusive, toInclusive, comparator, root, nullNode); } public NavigableSet headSet(K toElement, boolean inclusive) { return subSet(null, false, toElement, inclusive); } public NavigableSet tailSet(K fromElement, boolean inclusive) { return subSet(fromElement, inclusive, null, false); } public Comparator comparator() { return comparator; } public SortedSet subSet(K fromElement, K toElement) { return subSet(fromElement, true, toElement, false); } public SortedSet headSet(K toElement) { return subSet(null, false, toElement, false); } public SortedSet tailSet(K fromElement) { return tailSet(fromElement, true); } public K first() { if (isEmpty()) { return null; } if (from == null) { return root.first().key; } if (fromInclusive) { return ceiling(from); } return higher(from); } public K last() { if (isEmpty()) { return null; } if (to == null) { return root.last().key; } if (toInclusive) { return floor(to); } return lower(to); } public K get(int index) { if (index >= size() || index < 0) { throw new IndexOutOfBoundsException(Integer.toString(index)); } if (from != null) { index += headSet(from, !fromInclusive).size(); } return root.get(index); } protected int compare(K first, K second) { if (first == null || second == null) { return -1; } if (comparator != null) { return comparator.compare(first, second); } //noinspection unchecked return ((Comparable) first).compareTo(second); } protected class Node { protected final K key; protected final long priority; protected Node left; protected Node right; protected int size; protected Node(K key, long priority) { this.key = key; this.priority = priority; left = nullNode; right = nullNode; size = 1; } @SuppressWarnings({"unchecked"}) protected Object[] split(K key) { if (compare(key, this.key) < 0) { Object[] result = left.split(key); left = (Node) result[1]; result[1] = this; updateSize(); return result; } Object[] result = right.split(key); right = (Node) result[0]; result[0] = this; updateSize(); return result; } protected void updateSize() { size = left.size + right.size + 1; } @SuppressWarnings({"unchecked"}) protected Node insert(Node node) { if (node.priority > priority) { Object[] result = split(node.key); node.left = (Node) result[0]; node.right = (Node) result[1]; node.updateSize(); return node; } if (compare(node.key, this.key) < 0) { left = left.insert(node); updateSize(); return this; } right = right.insert(node); updateSize(); return this; } protected Node merge(Node left, Node right) { if (left == nullNode) { return right; } if (right == nullNode) { return left; } if (left.priority > right.priority) { left.right = left.right.merge(left.right, right); left.updateSize(); return left; } right.left = right.left.merge(left, right.left); right.updateSize(); return right; } protected Node erase(K key) { int value = compare(key, this.key); if (value == 0) { return merge(left, right); } if (value < 0) { left = left.erase(key); updateSize(); return this; } right = right.erase(key); updateSize(); return this; } protected Node lower(K key) { if (compare(key, this.key) <= 0) { return left.lower(key); } Node result = right.lower(key); if (result == nullNode) { return this; } return result; } protected Node floor(K key) { if (compare(key, this.key) < 0) { return left.floor(key); } Node result = right.floor(key); if (result == nullNode) { return this; } return result; } protected Node higher(K key) { if (compare(key, this.key) >= 0) { return right.higher(key); } Node result = left.higher(key); if (result == nullNode) { return this; } return result; } protected Node ceil(K key) { if (compare(key, this.key) > 0) { return right.ceil(key); } Node result = left.ceil(key); if (result == nullNode) { return this; } return result; } protected Node first() { if (left == nullNode) { return this; } return left.first(); } protected Node last() { if (right == nullNode) { return this; } return right.last(); } protected Node search(K key) { int value = compare(key, this.key); if (value == 0) { return this; } if (value < 0) { return left.search(key); } return right.search(key); } public int indexOf(Node node) { if (this == node) { return left.size; } if (compare(node.key, this.key) > 0) { return left.size + 1 + right.indexOf(node); } return left.indexOf(node); } public K get(int index) { if (index < left.size) { return left.get(index); } else if (index == left.size) { return key; } else { return right.get(index - left.size - 1); } } } private class NullNode extends Node { private Object[] splitResult = new Object[2]; private NullNode() { super(null, Long.MIN_VALUE); left = this; right = this; size = 0; } protected Object[] split(K key) { splitResult[0] = splitResult[1] = this; return splitResult; } protected Node insert(Node node) { return node; } protected Node erase(K key) { return this; } protected Node lower(K key) { return this; } protected Node floor(K key) { return this; } protected Node higher(K key) { return this; } protected Node ceil(K key) { return this; } protected Node first() { throw new NoSuchElementException(); } protected Node last() { throw new NoSuchElementException(); } protected void updateSize() { } protected Node search(K key) { return this; } } } static class OutputWriter { private final PrintWriter writer; public OutputWriter(OutputStream outputStream) { writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream))); } public OutputWriter(Writer writer) { this.writer = new PrintWriter(writer); } public void close() { writer.close(); } public void printLine(long i) { writer.println(i); } } }