滑动窗口--蓝桥杯真题子矩阵

一篇文章学会滑动窗口(单调队列) 超详细解释_滑动时间窗口的单调性-CSDN博客

AcWing 4964. 二维的单调队列(对一维再求一次就可) - AcWing

使用二维单调队列,先求出每行中长度为b的子列表的最大最小值,转化为最大、最小值矩阵(max, min),然后对这两个矩阵再次利用单调队列求出每列中长度为a的最大、最小值,更新max,min矩阵,最后求出所有max[i][j] * min[i][j]之和对998244353取模即可得到答案

from collections import deque

n, m, a, b = list(map(int, input().split()))
matrix = []

for i in range(n):
    lst = list(map(int, input().split()))
    matrix.append(lst)

def max_min_row(arr, func):
    ans = []
    q = deque()
    for i, v in enumerate(arr, 1):
        while q and q[0][0] <= i - b:   # 若队列第一个数为前一个窗口最左端的数,窗口移动后,该数不再出现在窗口中,则应删除
            q.popleft()
        while q and func(v, q[-1][1]):  # 若要增加的数v比单调递增队列中最后一个数小(或者比单调递减队列中最后一个数大)时,最后一个数必然不可能是最小(大)值,则将其从队列中删除
            q.pop()
        q.append((i, v))
        if i >= b:
            ans.append(q[0][1])
    return ans

def max_min_col(arr, index, func):
    ans = []
    q = deque()
    for i in range(0, n):
        v = arr[i][index]
        while q and q[0][0] <= i - a:
            q.popleft()
        while q and func(v, q[-1][1]):
            q.pop()
        q.append((i, v))
        if i + 1 >= a:
            ans.append(q[0][1])
    return ans

max_row, min_row, max_col, min_col = [], [], [], []
for i in range(0, n):
    max_row.append(max_min_row(matrix[i], lambda x, y : x > y))
    min_row.append(max_min_row(matrix[i], lambda x, y : x < y))

for i in range(0, m - b + 1):
    max_col.append(max_min_col(max_row, i, lambda x, y : x > y))
    min_col.append(max_min_col(min_row, i, lambda x, y : x < y))

res = 0
mod = 998244353
for i in range(0, m - b + 1):
    for j in range(0, n - a + 1):
        res = (res + max_col[i][j] * min_col[i][j]) % mod

print(res)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值