一维前缀和
给定数组 a[N] : a[1],a[2],a[3]......a[n];
前缀和公式: S[i] = a[1]+a[2]+ ... +a[i]
a[l]+ ... +a[r] = S[r] - S[l - 1]
作用:求一个数组任意区间元素的和
注:前缀和数组下标往往从1开始,并令S[0] = 0. 方便计算例如 S[10] - S[0] = a[1] + a[2] + ... +a[10] 这样的前缀和。
例题
#include <iostream>
using namespace std;
const int N = 100010;
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;
}
注:定义全局数组,若不进行初始化,数组中的各值为0; 定义局部数组,若不初始化,数组中的各值为随机值。 上述代码定义的是全局数组,所以S[0] = 0 可以省去。
二维前缀和
给定一个矩阵,求矩阵中子矩阵的和。
初始化:Sij = Si-1,j + Si,j-1 - Si-1,j-1 + aij
求和: Sx2,y2 - Sx2,y1-1 - Sx1-1,y2 + Sx1-1,y1-1
例题
#include <iostream>
using namespace std;
const int N = 10010;
int n,m,q;
int S[N][N];
int main()
{
scanf("%d%d%d",&n,&m,&q);
for(int i = 1; i <= n; i ++ )
for(int j = 1; j <= m; j ++ )
scanf("%d",&S[i][j]);
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] - S[i-1][j-1] + S[i][j]; //二维前缀和初始化
while(q -- )
{
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
printf("%d\n",S[x2][y2] - S[x2][y1-1] - S[x1-1][y2] + S[x1-1][y1-1]);
//二维子矩阵求和
}
return 0;
}