Here is a brief outline of O (n).
For each element, determine how many adjacent elements on the left are no more (call it a ), and how many adjacent elements on the right are less (call it b ). This can be done for all O (n) time elements - see MBo answer.
A single element is maximum in its window if the window contains an element and only elements from a on the left and b on the right. Taking the opportunity, the number of such windows of length k (and, therefore, the total contribution of these windows) is piecewise linear in k, with no more than five parts. For example, if a = 5 and b = 3 , then there are
1 window of size 1 2 windows of size 2 3 windows of size 3 4 windows of size 4 4 windows of size 5 4 windows of size 6 3 windows of size 7 2 windows of size 8 1 window of size 9.
The data structure that we need to efficiently code this contribution is the Fenwick tree, whose values ββare not numbers, but linear functions of k. For each linear part of the piecewise linear contribution function, we add it to the cell at the beginning of its interval and subtract it from the cell at the end (closed beginning, open end). At the end, we get all the prefix sums and evaluate them by index k to get the final array.
(OK, we need to complete it for now, but we donβt really need the Fenwick tree for the second step, which reduces complexity to O (n), and there may be a way to take the first step in linear time.)
Python 3 lightly tested:
def left_extents(lst): result = [] stack = [-1] for i in range(len(lst)): while stack[-1] >= 0 and lst[i] >= lst[stack[-1]]: del stack[-1] result.append(stack[-1] + 1) stack.append(i) return result def right_extents(lst): result = [] stack = [len(lst)] for i in range(len(lst) - 1, -1, -1): while stack[-1] < len(lst) and lst[i] > lst[stack[-1]]: del stack[-1] result.append(stack[-1]) stack.append(i) result.reverse() return result def sliding_window_totals(lst): delta_constant = [0] * (len(lst) + 2) delta_linear = [0] * (len(lst) + 2) for l, i, r in zip(left_extents(lst), range(len(lst)), right_extents(lst)): a = i - l b = r - (i + 1) if a > b: a, b = b, a delta_linear[1] += lst[i] delta_linear[a + 1] -= lst[i] delta_constant[a + 1] += lst[i] * (a + 1) delta_constant[b + 2] += lst[i] * (b + 1) delta_linear[b + 2] -= lst[i] delta_linear[a + b + 2] += lst[i] delta_constant[a + b + 2] -= lst[i] * (a + 1) delta_constant[a + b + 2] -= lst[i] * (b + 1) result = [] constant = 0 linear = 0 for j in range(1, len(lst) + 1): constant += delta_constant[j] linear += delta_linear[j] result.append(constant + linear * j) return result print(sliding_window_totals([5, 3, 12, 4]))