分块思想在算法中的工程化:平方分割与莫队算法的实现要诀

发布时间:2026/11/1 7:35:52

分块思想在算法中的工程化:平方分割与莫队算法的实现要诀 分块思想在算法中的工程化平方分割与莫队算法的实现要诀一、区间查询问题线段树不是唯一答案线段树是处理区间查询的经典数据结构单次查询 O(log n)功能强大。但它的实现代码量不小——建树、更新、查询三个递归函数一套下来至少几十行。而且不是所有场景都适合用线段树。如果数据是静态的不会在线更新或者查询的模式比较固定有没有比线段树更简单、更暴力但仍然够快的办法答案就是分块。分块思想的核心很简单把大规模数据按固定大小切成若干块预处理每块的聚合信息。查询时完整的块直接拿预计算的值零散的部分暴力计算。这样一次查询的复杂度在 O(sqrt(n)) 左右——比 O(log n) 慢一点但实现复杂度远低于线段树。在很多场景中O(sqrt(n)) 已经足够快。flowchart TD A[原始数组] -- B[按固定大小 sqrt#40n#41 分块] B -- C[块 0: 索引 0~B-1] B -- D[块 1: 索引 B~2B-1] B -- E[块 k: 索引 kB~n-1] C -- F[预计算块 0 的聚合值] D -- G[预计算块 1 的聚合值] E -- H[预计算块 k 的聚合值] I[区间查询 L, R] -- J{分析查询区间} J -- K[左边零散部分: 暴力遍历] J -- L[中间完整块: 直接用预计算值] J -- M[右边零散部分: 暴力遍历] K -- N[合并结果] L -- N M -- N二、平方分割最朴素的块最实用的效果平方分割是分块思想最基础的实现。假设数组长度为 n每块大小取 sqrt(n) 左右。为什么要取 sqrt(n)因为一次查询最多涉及 sqrt(n) 个完整块每块 O(1) 拿聚合值和两端各 sqrt(n) 个零散元素暴力计算——总复杂度 O(sqrt(n))。如果块大小取得太大零散部分变多如果块大小取得太小完整块变多。sqrt(n) 恰好在这两者之间取得最优平衡。以区间求和为例。每块预存块内元素的和。查询区间 [L, R] 时对于 L 所在的块中从 L 到块尾的部分逐个累加。对于 L 和 R 之间的完整块取出预计算的和O(1) 搞定。对于 R 所在的块中从块头到 R 的部分逐个累加。更新操作同样简单修改元素值后更新该元素所在块的聚合值。整个实现不超过 40 行代码。三、莫队算法把分块用在查询重排上分块不仅能优化数据结构还能优化查询的执行顺序。莫队算法就是这样一个技巧当有大量离线区间查询不需要在线返回、允许批量处理后一并输出时通过调整查询的执行顺序让指针移动的总次数从 O(mn) 降到 O(nsqrt(m))。莫队算法的核心操作是把所有查询按左端点所在块号排序同块内的按右端点排序。排序后维护两个指针 L 和 R表示当前处理到的区间。处理下一个查询时通过移动 L 和 R 来覆盖目标区间。因为排序后的查询顺序让指针的移动距离大大缩短总体复杂度从平方降到了 n*sqrt(m)。/** * 莫队算法离线区间查询优化 * * 适用条件 * 1. 查询是离线的不需要立刻回答 * 2. add/remove 操作是 O(1) 的可逆操作 * 3. 查询之间相互独立 * * 复杂度O(n * sqrt(m))n 是数组长度m 是查询数量 */ public class MoAlgorithm { // 块大小n / sqrt(m)使总复杂度最优 private int blockSize; /** * 处理所有区间查询 * * param arr 原始数组 * param queries 所有查询 [l, r, index] * return 按原始顺序排列的查询结果 */ public int[] processQueries(int[] arr, int[][] queries) { int n arr.length; int m queries.length; // 块大小理论最优值为 n / sqrt(m) // 这里用 n / Math.sqrt(m) 是为了让指针移动次数最少 blockSize (int) (n / Math.sqrt(m)); if (blockSize 0) blockSize 1; // 第一步将查询按莫队排序规则排列 // 规则1左端点所在块号小的排前面 // 规则2同块内按右端点排序奇数块升序、偶数块降序进一步优化 Query[] qs new Query[m]; for (int i 0; i m; i) { qs[i] new Query(queries[i][0], queries[i][1], i); } Arrays.sort(qs, (a, b) - { int blockA a.l / blockSize; int blockB b.l / blockSize; if (blockA ! blockB) { return blockA - blockB; } // 奇偶块排序优化减少 R 指针的无谓移动 return (blockA % 2 0) ? a.r - b.r : b.r - a.r; }); // 第二步从头开始处理所有查询维护 [curL, curR] 区间 int curL 0, curR -1; int curSum 0; // 当前区间的聚合值以求和为例 int[] results new int[m]; for (Query q : qs) { // 扩展右边界包含更多元素 while (curR q.r) { curR; curSum arr[curR]; // add 操作O(1) } // 收缩右边界排除多余元素 while (curR q.r) { curSum - arr[curR]; // remove 操作O(1) curR--; } // 扩展左边界包含更多左侧元素左边界左移 while (curL q.l) { curL--; curSum arr[curL]; // add 操作O(1) } // 收缩左边界排除多余左侧元素左边界右移 while (curL q.l) { curSum - arr[curL]; // remove 操作O(1) curL; } // 四个 while 的顺序很重要 // 先扩后缩可以避免指针交叉导致的数组越界 results[q.index] curSum; } return results; } /** * 查询内部类 */ private static class Query { int l, r; // 查询区间 [l, r] int index; // 原始顺序用于恢复输出顺序 Query(int l, int r, int index) { this.l l; this.r r; this.index index; } } }四个 while 循环的顺序不是随意排列的。基本原则是先扩展再收缩避免指针位置非法。如果先收缩左边界while (curL q.l) curL在 curR 还没扩展到位的情况下curL 可能越过 curR造成 sum 减去了不该减的元素。正确的顺序是先扩展右边界和左边界再收缩右边界和左边界。四、分块方法的适用场景与限制分块思想的优势在于实现简单和适用面广。不像线段树需要预定义区间操作的类型和、最大值、最小值分块对区间操作的类型几乎没有限制——只要块的聚合能快速更新就行。而且分块天然支持单点更新这一点比前缀和要灵活。但它的劣势也同样明确在线查询时 O(sqrt(n)) 比 O(log n) 慢n 达到 10^6 时差距就明显了。莫队只适用于离线查询需要拿到全部查询后才能重排。分块的常数因子不小块大小、排序策略都会影响实际效率需要针对具体数据做调优。分块和线段树不是替代关系而是互补关系。复杂动态区间操作如区间乘加混合更新用线段树简单静态或偶有更新的数据用分块。选择的依据是实现的复杂度 VS 查询的复杂度哪个在你的场景里权重更高。五、总结分块思想用暴力 预处理的组合在 O(sqrt(n)) 的复杂度下解决了区间查询问题。平方分割是最基础的分块应用莫队算法则把分块引入查询重排领域大幅减少离线批量查询中指针移动的总次数。分块的魅力不在于复杂度和实现有多精致而在于思路的直白——把大的拆成小的整块的巧算零散的死算。这种简单但有效的套路在实际工程中比精巧但脆弱的数据结构更值得信赖。
延伸阅读

更多相关文章

2026/11/1 7:34:35

AI 工具的用户反馈闭环:从隐性信号到模型优化

AI 工具的用户反馈闭环:从隐性信号到模型优化 一、用户反馈不只是「好评」和「差评」 独立产品的用户反馈,传统形式是评分(1-5星)或评论。对于 AI 工具,这些显式反馈(用户主动给出的评价)有价值,但其覆盖率通常不到 1%——绝大多数用户不会主动评价。如果只依赖显…

2026/10/25 15:37:46

AI 任务的优先级调度:不同用户、不同任务的资源分配

AI 任务的优先级调度:不同用户、不同任务的资源分配 一、当 AI 调用开始排队 产品在成长期,AI 调用量不再是「即来即处理」。在高并发时刻(如工作时间、产品推广期),AI API 的请求可能会出现排队——用户的请求发出了,但需要等待前面的请求处理完才能轮到。 如果所有…

2026/10/24 8:23:31

【AI问数】大模型选型与微调:AI问数的LLM落地实战

4 大选型维度 多模型 路由策略 99.97% 可用性 Spider 权威Benchmark AI问数对LLM的选型要求:中文理解强、SQL生成能力突出(Spider/Bird跑分)、上下文窗口足够(16K)、支持私有化部署。鲲溟KM AI采用多模型路由:主模型专用模型备用模型三层配置。 一…

2026/11/1 2:01:37

1.c++入门篇

1.c中的关键字asmdoifreturntrycontinueautodoubleinlineshorttypedefforbooldynamic_castintsignedtypeidpublicbreakelselongsizeoftypenamethrowcaseenummutablestaticunionwchar_tcatchexplicitnamespacestatic_castunsigneddefaultcharexportnewstructusingfriendclassext…

2026/11/1 2:01:37

《江灯合声》:有可行的分框版,也仍可以选择连续鸣谢

武汉江岸区栎坡合唱团在免费节目册《江灯合声》中,以表格集中鸣谢资助者。各家共同要求改为独立小框,团里仍想保留表格。现有全名与支持事项清楚可见,双方此前未承诺具体排版。我支持保留表格。补充的试排材料让选择更具体:分框能…

2026/11/1 2:01:37

关于“贾子猜想”的数学地位、结构特征与讨论边界

关于“贾子猜想”的数学地位、结构特征与讨论边界摘要 本文对“贾子猜想”进行基于公开表述与现有数学事实的分析。该猜想主张:当正整数 n3m>5(即 n6,9,12,15,…)时,方程x₁ⁿ x₂ⁿ ⋯ xₙⁿ yⁿ不存在正整数解。文章首先…

2026/11/1 2:01:37

启动报Port 8088 was already in use?先查是谁占的

启动报Port 8088 was already in use?先查是谁占的 项目启动报 Port 8088 was already in use,意思很直白:这个端口已经有人占了。 先说原理:端口是"门牌号",一间房只住一个进程 端口就是一台机器上的门牌号…

2026/11/1 2:01:37

担心文档上云?本地运行的办公AI才敢放心用

单位上周开了个会,主题是"AI 提效",散会时领导补了一句:涉及客户资料的文档,不许往云端传。这话一出,会议室里本来跃跃欲试的同事全蔫了——大家平时用的那些在线 AI,文档一上传就不知道存哪儿去…

2026/11/1 1:56:37

华为OD机试真题 新系统 2026-10-28 JavaGoC【社交网络消息转发】

目录 题目 思路 Code 题目 题目内容: 在一个社交网络中,有 N 个用户(编号 0 到 N−1);每个用户都有一个「转发名单」(整数),该数二进制格式中的第 i 位为 1 表示此用户会把消息转发给第 i 个用户。 给定一个整数数组 forwardLists 和一个整数 initialSenders,请…

2026/11/1 0:01:26

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/1 1:01:33

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/1 0:01:26

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/1 1:01:33

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/1 0:01:26

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/1 1:01:33

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑