对于一个数组a[i],我们建立一个数组s[i],使得:
s[i]= a[1] + a[2] + …… + a[i]
这方便我们求原数组a[i]在i属于[l, r]之间的所有元素的和。
我们可以通过s[r] - s[l - 1]很方便地计算出:
a[l] + a[l + 1] + …… + a[r]
这样我们就可以用仅仅一次运算就运算出一个数组中任意区间中元素的加和。
如果本来没有前缀和数组,我们计算任意区间中元素的和的时间复杂度是O(n)
但是如果有了前缀和数组,时间复杂度此后就可以降为O(1),其实是通过定义了s[0]使得每次计算少了一个if判断。
整个算法其实就两部分:
定义s[0] = 0
加和
eg:
输入一个长度为n的整数序列。
接下来再输入m个询问,每个询问输入一对l, r。
对于每个询问,输出原序列中从第l个数到第r个数的和。
#include<iostream>
using namespace std;
const int N = 1e6 + 10;//我一直先定义常量然后在后面用常量来建立数组,
//因为这样方便我同时修改所有数组的大小
//否则好几个数组长度一个个改太烦了也容易错
int n, m;
int a[N], s[N];
int main () {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i ++) scanf("%d", &a[i]);
for(int i = 1; i <= n; i ++) s[i] = s[i - 1] + a[i];
while(m -- ) {
int l, r;
scanf("%d%d", &l, &r);
printf("%d\n", s[r] - s[l - 1]);
}
return 0;
}
前缀和代码虽然很简单,但是真的很有用。总是忘记用,又总是捡回来用。