【Kickstart】2019 Round C - Circuit Board

解法

算出每列往左的长度,然后就能转化成求直方图最大矩形的问题

至于如何求第i行第j列往左有多长,需要每行维护两个双向队列minStackmaxStack和一个左边界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)))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值