一维前缀和
前缀和可以办o(n)的复杂度变为0(1)
对于前缀和只要理解和记住公式就可以了
s[i]=s[i-1]+a[i]//公式
经典例题:求一段区间的和
#include<iostream>
using namespace std;
const int N=10010;
int n,m;
int a[N],s[N];
int main1()//一维前缀和
{
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];//前缀和初始化,s[i]是前a[i]的和;
while(m--)
{
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n", s[r] - s[l - 1]); // 区间和的计算
}
return 0;
}
二维前缀和
s[i][j]=s[i-1][j]+s[i][j-1] -s[i-1][j-1] +a[i][j]
公式推导
面积方法理解
(i,j)可以由(i-1,j)和(i,j-1)两块构成,不过要注意两个点,1、有一块矩阵我们重复加了,也就是(i-1,j-1)这一块,所以我们要减去它。2、我们这个矩阵是不完整的,由图可知我们还有一块深蓝色的没有加,也就是(i,j)这一点,所以我们要再加上a[i][j]也就是题目给出的矩阵中这一格的数。
代数方法理解
例题 求子矩阵的和
s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1])//可以·用面积·理解
```c
```c
#include<iostream>
using namespace std;
const int N=10010;
int q;
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]);
printf("++");
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];//前缀和数组
while(q--)
{
int x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
printf("%d",s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]);
}
return 0;
}