首先看题目范围,如果暴力解,大概是四个for循环,显然不太ok。
考虑前缀和,max和min维护一个表,也不能求出某个矩阵的最大值,最小值。
想到滑动窗口维护最大值或者最小值,但它是二维矩阵,可以先对每一行滑动维护一个大小为b的窗口,再对每一列维护一个大小为a的窗口。
维护最大值,最小值窗口,特别需要注意,当遍历到第i个元素时,查看栈顶元素是否等于第i-b个元素,此元素不在边长为b的滑动窗口中。
from collections import deque
def max_(ls, leth):
qu = deque()
ans = []
for idx in range(len(ls)):
num = ls[idx]
while qu and qu[-1] < num:
qu.pop()
qu.append(num)
if idx - leth >= 0 and ls[idx-leth] == qu[0]:
qu.popleft()
if idx + 1 >= leth:
ans.append(qu[0])
return ans
def min_(ls, leth):
qu = deque()
ans = []
for idx in range(len(ls)):
num = ls[idx]
while qu and qu[-1] > num:
qu.pop()
qu.append(num)
if idx - leth >= 0 and ls[idx-leth] == qu[0]:
qu.popleft()
if idx + 1 >= leth :
ans.append(qu[0])
return ans
xyz = 998244353
n,m, a,b = map(int,input().split())
# 横向压入,长度为b
max_v = []
min_v = []
for idy in range(n):
ls = list(map(int,input().split()))
max_v.append(max_(ls, b))
min_v.append(min_(ls, b))
# 旋转矩阵,旋转后的矩阵为 m-b+1*n
m1 = [ [0]*(n) for _ in range(m-b+1)]
m2 = [ [0]*(n) for _ in range(m-b+1)]
for i in range(m-b+1):
for j in range(n):
m1[i][j] = max_v[j][i]
m2[i][j] = min_v[j][i]
# 纵向压入,长度为a
max_h = []
min_h = []
for idy in range(m-b+1):
max_h.append(max_(m1[idy], a))
min_h.append(min_(m2[idy], a))
ans = 0
for idx in range(m-b+1):
for idy in range(n-a+1):
ans += max_h[idx][idy] * min_h[idx][idy]
print(ans%xyz)