【c++提高1】数据结构之分块(预处理+暴力)

本文介绍了C++中的分块思想及其应用。通过将区间划分为块并预处理每个块,可以在查询时达到较高的效率。文章详细讲解了如何预处理块,包括计算每个位置所属的块编号,并针对不同问题预处理块内的信息。同时,讨论了分块查询的方法,如查询[l, r]区间和,强调了整块和零散块的处理,指出其时间复杂度约为O(sqrt(n))。" 123317605,12688308,使用knife4j实现微服务接口文档,"['微服务', 'spring boot', 'spring cloud', '接口文档']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大纲

1.分块思想
2.分块实现操作

1.分块思想

分块的思想是将整个区间划分成一些区间,预处理每一个块,这个过程就是分块的过程。
分块的时间复杂度在于块的大小,块的大小关乎最终的复杂度。
在数学中可以推导出来,当块的大小m=sqrt(n)的时候,时间复杂度是最小的。
在这里插入图片描述

2.分块实现操作

2.1.预处理块

首先要预处理[1, n]中每一个位置属于的块编号,belong[i]表示位置i所划分的块编号。
在这里插入图片描述接下来根据题目的主要逻辑,将每一个块预处理答案。
就比如求和,每一个块都预处理一下它的和,时间复杂度O(n)就是O(sqrt(n)*sqrt(n)),共sqrt(n)的块,每个块长度为sqrt(n),计算和就是sqrt(n)*sqrt(n)。
在这里插入图片描述

2.2.分块查询

假设现在查询[l, r]的和,运用预处理的块。
就比如这个查询:

<< 下面是解决您提到的USACO问题的C++完整代码。这个版本采用了简单的暴力枚举法,适合中小规模的数据。如果数据规模较大,则可以考虑使用高级数据结构如线段树或分块技术来优化性能。 ```cpp #include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { int N, Q; cin >> N >> Q; // 输入牛的数量和查询次数 vector<int> heights(N); // 存储每头牛的身高 for (int i = 0; i < N; ++i) { cin >> heights[i]; // 输入每头牛的身高 } while (Q--) { // 对于每一个查询 int A, B; cin >> A >> B; // 输入查询区间 [A, B] // 计算当前区间中的最大值和最小值 int current_min = heights[A - 1]; int current_max = heights[A - 1]; for (int i = A; i <= B; ++i) { if (heights[i - 1] < current_min) { current_min = heights[i - 1]; } if (heights[i - 1] > current_max) { current_max = heights[i - 1]; } } cout << (current_max - current_min) << endl; // 输出高度差 } return 0; } ``` --- ### **代码说明** 1. **变量定义:** - `N`: 牛的数量。 - `Q`: 查询次数。 - `heights[]`: 用于存储每头牛身高的数组。 2. **核心逻辑:** - 先输入所有的牛高信息存入`heights[]`数组。 - 针对每一次询问: - 初始化当前区间的最小值和最大值为第一个元素的值。 - 使用循环迭代计算出该区间内的最小值和最大值。 - 打印两者的差异作为结果。 3. **注意点:** - 用户提供的索引是以`1-based`形式传入的 (`A`, `B`),因此在访问数组时需减去`1`转换为`0-based`。 - 这种做法适用于较小的数据集;若遇到更大的数据量,请尝试更高效的技术(例如线段树)。 --- ### 性能分析 - 时间复杂度:对于每个查询,都需要遍历整个指定的区间,总的时间复杂度为 \( O(Q \times K) \),其中 \( K \) 是每次查询所涉及的平均节点数目。 - 空间复杂度:\( O(N) \),仅需要保存所有牛的高度数据。 --- **优化建议:** 如果您希望处理更大范围的数据,推荐采用以下几种方法之一: 1. 构建稀疏表(Sparse Table)实现 RMQ(Range Minimum/Maximum Query)预处理。 2. 实现线段树或其他支持快速区间查询的数据结构。 ---
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

{∞}

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值