deq = collections.deque()
for i, a_i in enumerate(A):
while deq[0][1] <= i - L:
deq.popleft()
while deq and deq[-1][0] >= a_i:
deq.pop()
deq.append((a_i, i))
min_val = deq[0][0] # min_val == min(A[i-L+1], ... , A[i])
deq = collections.deque()
for i, a_i in enumerate(A):
if i >= L and deq[0] == A[i - L]:
deq.popleft()
while deq and deq[-1] > a_i:
deq.pop()
deq.append(a_i)
min_val = deq[0] # min_val == min(A[i-L+1], ... , A[i])
deq = collections.deque()
for left, right in zip(itertools.chain([None] * L, A), A):
while deq and deq[-1] > right:
deq.pop()
deq.append(right)
if deq[0] == left:
deq.popleft()
min_val = deq[0] # min_val == min(A[i-L+1], ... , A[i])
deq = collections.deque([INF])
dp = [None] * N
for i in range(N):
min_val = deq[0]
dp[i] = f(i, min_val)
while deq and deq[-1] > dp[i]:
deq.pop()
deq.append(dp[i])
if deq[0] == dp[i - K]:
deq.popleft()