This commit is contained in:
programmercarl
2024-06-30 15:46:16 +08:00
parent bcbd631dc9
commit 686c3a5580
9 changed files with 466 additions and 48 deletions

View File

@@ -0,0 +1,191 @@
# 58. 区间和
[题目链接](https://kamacoder.com/problempage.php?pid=1070)
题目描述
给定一个整数数组 Array请计算该数组在每个指定区间内元素的总和。
输入描述
第一行输入为整数数组 Array 的长度 n接下来 n 行,每行一个整数,表示数组的元素。随后的输入为需要计算总和的区间,直至文件结束。
输出描述
输出每个指定区间内元素的总和。
输入示例
```
5
1
2
3
4
5
0 1
1 3
```
输出示例
```
3
9
```
数据范围:
0 < n <= 100000
## 思路
本题我们来讲解 数组 上常用的解题技巧前缀和
首先来看本题我们最直观的想法是什么
那就是给一个区间然后 把这个区间的和都累加一遍不就得了是一道简单不能再简单的题目
代码如下
```CPP
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, a, b;
cin >> n;
vector<int> vec(n);
for (int i = 0; i < n; i++) cin >> vec[i];
while (cin >> a >> b) {
int sum = 0;
// 累加区间 a 到 b 的和
for (int i = a; i <= b; i++) sum += vec[i];
cout << sum << endl;
}
}
```
代码一提交,发现超时了.....
我在制作本题的时候,特别制作了大数据量查询,卡的就是这种暴力解法。
来举一个极端的例子如果我查询m次每次查询的范围都是从0 到 n - 1
那么该算法的时间复杂度是 O(n * m) m 是查询的次数
如果查询次数非常大的话,这个时间复杂度也是非常大的。
接下来我们来引入前缀和,看看前缀和如何解决这个问题。
前缀和的思想是重复利用计算过的子数组之和,从而降低区间查询需要累加计算的次数。
**前缀和 在涉及计算区间和的问题时非常有用**
前缀和的思路其实很简单,我给大家举个例子很容易就懂了。
例如,我们要统计 vec[i] 这个数组上的区间和。
我们先做累加,即 p[i] 表示 下标 0 到 i 的 vec[i] 累加 之和。
如图:
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20240627110604.png)
如果我们想统计在vec数组上 下标 2 到下标 5 之间的累加和,那是不是就用 p[5] - p[1] 就可以了。
为什么呢?
p[1] = vec[0] + vec[1];
p[5] = vec[0] + vec[1] + vec[2] + vec[3] + vec[4] + vec[5];
p[5] - p[1] = vec[2] + vec[3] + vec[4] + vec[5];
这不就是我们要求的 下标 2 到下标 5 之间的累加和吗。
如图所示:
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20240627111319.png)
p[5] - p[1] 就是 红色部分的区间和。
而 p 数组是我们之前就计算好的累加和,所以后面每次求区间和的之后 我们只需要 O(1)的操作。
```CPP
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, a, b;
cin >> n;
vector<int> vec(n);
vector<int> p(n);
int presum = 0;
for (int i = 0; i < n; i++) {
cin >> vec[i];
presum += vec[i];
p[i] = presum;
}
while (cin >> a >> b) {
int sum;
if (a == 0) sum = p[b];
else sum = p[b] - p[a - 1];
cout << sum << endl;
}
}
```
```CPP
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, a, b;
cin >> n;
vector<int> vec(n);
vector<int> p(n);
int presum = 0;
for (int i = 0; i < n; i++) {
scanf("%d", &vec[i]);
presum += vec[i];
p[i] = presum;
}
while (~scanf("%d%d", &a, &b)) {
int sum;
if (a == 0) sum = p[b];
else sum = p[b] - p[a - 1];
printf("%d\n", sum);
}
}
```
```CPP
#include<bits/stdc++.h>
using namespace std;
int main(){
int n, a, b;
cin >> n;
vector<int> vec(n + 1);
vector<int> p(n + 1, 0);
for(int i = 1; i <= n; i++) {
scanf("%d", &vec[i]);
p[i] = p[i - 1] + vec[i];
}
while(~scanf("%d%d", &a, &b)){
printf("%d\n", p[b + 1] - p[a]);
}
return 0;
}
```