前缀和算法
常规写法:弊端 → 数值大的话运行时间可能会超时!
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10; /*科学计数法*/
int a[N],n,m;
int main(){
/*
例题:计算能力
给定一个数列,求出m段连续段的和
*/
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
/*求出m段连续段的和*/
超时的原因:
for(int i=1;i<=m;i++){
/*求出区间x ~ y的总和*/
int x,y;
cin>>x>>y;
/*求和*/
int sum = 0;
for(int j=x;j<=y;j++){
sum += a[j];
}
cout<<sum<<endl;
}
return 0;
}
s[i] = s[i-1] + a[i] | ||||||
下标 | 1 | 2 | 3 | 4 | 5 | 6 |
a | 1 | 2 | 3 | 4 | 5 | 6 |
s | 1 | 3 | 6 | 10 | 15 | 21 |
s数组的第i个位置的值表示a数组1~i区间的值 |
求a数组区间2 ~ 4 的总和:a[2] + a[3] + a[4] → 前缀和数组s中:s[4] - s[1]
s[4] = a[1] + a[2] + a[3] + a[4]
s[1] = a[1]
s[4] - s[1] = a[1] + a[2] + a[3] + a[4] - a[1] = a[2] + a[3] + a[4]
前缀和代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10; /*科学计数法*/
int a[N];/*初始数组*/
int s[N];/*前缀和数组*/
int n,m;
int main(){
/*
计算能力
给定一个数列,求出m段连续段的和
*/
cin>>n>>m;
/*① 处理好初始数组 */
for(int i=1;i<=n;i++){
cin>>a[i];
}
/*② 求出a数组的前缀和数组s*/
for(int i=1;i<=n;i++){
s[i] = s[i-1] + a[i];
}
/*③ 求a数组中的连续区间(x ~ y)的和:利用s数组*/
for(int i=1;i<=m;i++){
int x,y;
cin>>x>>y;
/*利用s数组求连续区间的和*/
int ans = s[y] - s[x-1];
cout<<ans<<endl;
}
return 0;
}
应用场景:数据过大,且求数列中连续区间的和
利用前缀和数组求连续k段
for(int i=k;i<=n;i++){
int temp = s[i] - s[i-k];
temp就是a数组中连续k段的和
}