class Line: def __init__(self, a, b): self.a = a self.b = b def get(self, x): return self.a * x + self.b class LiChaoTree: def __init__(self, x_min, x_max): self.x_min = x_min self.x_max = x_max self.nodes = [] self.nodes.append({'l': x_min, 'r': x_max, 'line': None, 'left': -1, 'right': -1}) def insert_line(self, new_line): stack = [0] while stack: node_idx = stack.pop() node = self.nodes[node_idx] l, r = node['l'], node['r'] if node['line'] is None: node['line'] = new_line continue current_line = node['line'] m = (l + r) // 2 cl_l = current_line.get(l) nl_l = new_line.get(l) cl_r = current_line.get(r) nl_r = new_line.get(r) if nl_l > cl_l and nl_r > cl_r: node['line'] = new_line continue if nl_l <= cl_l and nl_r <= cl_r: continue cl_m = current_line.get(m) nl_m = new_line.get(m) if nl_m > cl_m: node['line'], new_line = new_line, current_line if new_line.get(l) > current_line.get(l): if node['left'] == -1: new_node = {'l': l, 'r': m, 'line': None, 'left': -1, 'right': -1} self.nodes.append(new_node) node['left'] = len(self.nodes) - 1 stack.append(node['left']) else: if node['right'] == -1: new_node = {'l': m + 1, 'r': r, 'line': None, 'left': -1, 'right': -1} self.nodes.append(new_node) node['right'] = len(self.nodes) - 1 stack.append(node['right']) def query(self, x): res = -float('inf') node_idx = 0 while node_idx != -1: node = self.nodes[node_idx] line = node['line'] if line is not None: res = max(res, line.get(x)) m = (node['l'] + node['r']) // 2 if x <= m: next_node = node['left'] else: next_node = node['right'] node_idx = next_node return res def main(): import sys input = sys.stdin.read().split() N = int(input[0]) Q = list(map(int, input[1:N+1])) tree = LiChaoTree(-10**18, 10**18) max_E = -float('inf') for i in range(N): q = Q[i] if i == 0: tree.insert_line(Line(q, 0)) else: current = tree.query(q) tree.insert_line(Line(q, current)) if current > max_E: max_E = current print(max_E) if __name__ == "__main__": main()