主要解决的问题
- 可以求任意区间之和
- 也可以在数组上求段某区间之和的最值(推荐双指针&&滑动窗口)
1.一维前缀和
1.1 算法步骤
- 求每个数组下标的前 n 项和,n = 2就是前2项,n = 3就是前3项
- 这时输入的 L 和 R,我们直接用 arr[R] - arr[L-1] 就算出了区间 [ L , R]的前缀和
1.2 代码实现
#include<iostream>
using namespace std;
#include<vector>
int main(){
// 1.读入数据
int n, q;
cin >> n >> q;
vector<int> arr(n + 1);
for (int i = 1; i <= n;i++){
cin >> arr[i];
}
// 2.预处理数组的前缀和
vector<int> s(n + 1);
for (int i = 1; i <= n;i++){
s[i] = s[i - 1] + arr[i];
}
// 3.使用前缀和数组
int l = 0, r = 0;
while(q--){
cin >> l >> r;
cout << s[r] - s[l - 1];
}
return 0;
}
2.二维前缀和
2.1 算法步骤
和一维思路一样,
2.2 代码实现
#include <iostream>
using namespace std;
#include <vector>
int main(){
// 1.读入数据
int n, m,q;
cin >> n >> m >> q;
vector<vector<int>> array(n + 1, (vector<int>(m + 1)));
for (int i = 1; i <= n;i++){
for (int j = 1; j <= m;j++){
scanf("%d", &array[i][j]);
}
}
// 2.预处理二维数组求其前缀和
vector<vector<int>> s(n + 1, (vector<int>(m + 1)));
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
s[i][j] = s[i - 1][j] + s[i][j - 1] + array[i][j] - s[i - 1][j - 1];
}
}
// 3.使用预处理的前缀和
int x1 = 0, y1 = 0, y2 = 0,x2 = 0;
while(q--){
cin >> x1 >> y1 >> x2 >> y2;
cout << s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1];
}
return 0;
}