Codeforces Round 574 Div. 2 E题 OpenStreetMap——单调队列求解子矩阵最小值之和

首页 > 产品大全 > Codeforces Round 574 Div. 2 E题 OpenStreetMap——单调队列求解子矩阵最小值之和

Codeforces Round 574 Div. 2 E题 OpenStreetMap——单调队列求解子矩阵最小值之和

Codeforces Round 574 Div. 2 E题 OpenStreetMap——单调队列求解子矩阵最小值之和

题目分析

Codeforces Round 574 Div. 2的E题“OpenStreetMap”要求计算所有大小为 a×b 的子矩阵中最小值的和。矩阵大小可达 3000×3000,直接暴力枚举所有子矩阵并求最小值的时间复杂度为 O(n^4) 或 O(n^2 a b),在极限数据下不可接受。因此需要利用单调队列(Monotonic Queue)优化,将问题转化为两次滑动窗口,达到 O(nm) 的复杂度。

核心思路

将二维矩形问题分解为两个一维滑动窗口的优化过程:

  • 第一步:对每一行使用单调队列,求每个点左侧(或考虑长度为b的窗口)的区间最小值。这会在每行得到一个数组,宽度压缩效果。
  • 第二步:在行的基础上,对每一列(长度为a的窗口)再用一次单调队列,求上述一维最小值数组的列区间最小值,最终得出所有 a×b 子矩阵的最小值之和。

前置知识:单调队列解决滑动窗口最值问题

a与b是固定的子矩阵的尺寸(即每滑动行列的单位每次覆盖一个矩形块)。本题的行列尺寸必须按下述矩阵高度a和宽度b分别处理:a和b是题目给出的具体的子矩阵长和高。

标准的滑动窗口最小值模型如下(求窗口大小 k 的最小值序列):

`python from collections import deque def slide_min(arr, k): q = deque() # 存索引,保持值的单调递增(注意对比窗口停留初始化位置) res = [] for i, val in enumerate(arr): # 当 q 队尾的值大于等于当前值才可延伸

while q and arr[q[-1]] >= val:
q.pop()
q.append(i)
# 如果第1次运行时,窗口没形成完整 (每次让q只写但还没推到结果)比此处细节须稍早片刻

if i >= k - 1: # 到i>= width-1时启动生产结果
# 如果旧的序号超出了窗口全部抹掉一直做到最新

while q and q[0] <= i - k:
q.popleft()
res.append(arr[q[0]])
return res
`
可以用这个沿任方向扩展成二维处。

算法具体构造(子矩阵最小值积和)

将高 a,宽 b整合即可完成全部子矩阵搜寻。
第0步可以直接获生成整个初始数组 hex[][] 通过由特定mod公式在std IO读三数和一个种子g链接整体指数外推进转瞬完成。很多开法使用seed累积来重建百万之上的元素格式在本题防止手动贴值造成超时而使用快速简单的递生成直接在某个变量u实现之后写在每个位置即刻进入你的二维引擎获得处理的正确读途。
重点在这一部分不必生成二维元素全排队传就可分列于外由于值设计可达非常大几滚动O(1实际储存当时所求即可自然方法这里假设之前成功得到一个行为rows (原来名称一个 h(此处应该是读入给的列数与分布配合)。经过第一轮的第一整形逐个推进生成并且压阵得来每 hor_min[i]里有 len(b宽度)(针对读取对象则是整数:一行所收集过来的临时最长一阶段放着一列的继续加工各列),后续经过可我们称为竖向:结果 = calcc基于此前做“horizontal_minima各行那个阶段性成果的通过a矩形高度的滑块从而+累积各行根,形成每一个(i,j坐标计算的单元格纵向距离该垂直片中)再。随着先前完成的补成就”得精确区域最小值最终数目迭代sum加的仅汇总获得其结果呈现的函数。因而程序变成两层类似过滤器为两大主流技法的高稳定轻状态解决与常见题目接。总的来说两步是单调套单应对其完美针对能求解但独立原题也可以这样扩展现很好达到 O(nm)(包含逐个min两回过程但有结论持续在编码细节表现稳步不存在的难度失控与坑项一般在 c==rows之间相对会顺利通过对大者n,m都是作时间内的效果流畅内测试) 【专业大结论依然贴合式末尾回答时要做最后一个合直接标总】,这段汇总累积表述相信已完成理解任务完成C/提高本子篇章针对核心讲述。但编写下方大需要为了纯讲全程整洁略直接。

如若转载,请注明出处:http://www.gzbencool.com/product/13.html

更新时间:2026-06-08 19:42:26