【Kickstart】2019 Round C - Circuit Board
作者:互联网
解法
算出每列往左的长度,然后就能转化成求直方图最大矩形的问题
至于如何求第i行第j列往左有多长,需要每行维护两个双向队列minStack
、maxStack
和一个左边界l
,对于范围(l,j]
,minStack
队头是这个范围内最小值(以及它在的位置),从队头到队尾,值和索引都是递增的
类似地,maxStack
队头是这个范围内最大值(以及它在的位置),从队头到队尾,值递减,索引都是递增的
现在如果maxStack[0]-minStack[0]>K
,说明极差过大,这时候可以:
- 选择增大最小值,也就是把
minStack
队头pop出去,同时将左边界移到这个元素的位置 - 选择减小最大值,也就是把
maxStack
队头pop出去,同时将左边界移到这个元素的位置
显然,我们得选择两种方案里使得左边界更小的那种
# -*- coding:utf-8 -*-
def solve(r,c,k,V):
from collections import deque
minStack = [deque() for _ in range(r)]
maxStack = [deque() for _ in range(r)]
l = [-1]*r
ans = 0
for j in range(c):
stack = deque([(-1, -1)])
for i in range(r):
while minStack[i] and V[i][minStack[i][-1]]>=V[i][j]:
minStack[i].pop()
minStack[i].append(j)
while maxStack[i] and V[i][maxStack[i][-1]]<=V[i][j]:
maxStack[i].pop()
maxStack[i].append(j)
while V[i][maxStack[i][0]]-V[i][minStack[i][0]]>k:
if maxStack[i][0]<minStack[i][0]:
l[i] = maxStack[i].popleft()
else:
l[i] = minStack[i].popleft()
h = j - l[i]
while stack and stack[-1][0]>=h:
hh = stack.pop()[0]
ans = max(ans, hh * (i-stack[-1][1]-1))
stack.append((h, i))
while len(stack)>1:
h = stack.pop()[0]
ans = max(ans, h * (r-stack[-1][1]-1))
return ans
if __name__ == "__main__" :
t = int(input())
for round in range(1,t+1):
r,c,k = map(int,input().split())
V = [list(map(int,input().split())) for _ in range(r)]
print("Case #%d: %d"%(round,solve(r,c,k,V)))
标签:maxStack,Kickstart,minStack,pop,stack,range,2019,ans,Round 来源: https://blog.csdn.net/lemonmillie/article/details/100066856