前缀和分为一维 二维
一维前缀和: 下标必须从1开始 si = a1+a2+a3+...+ai s0 = 0
习惯性将输入将预处理出前缀和数组合二为一降低时间
作用:快速求出原数组中一段数的和 [l,r] sr-s(l-1)
这样做有什么好处?O(nm)->O(max(n,m)) n是数组长度 m是查询次数 降低时间复杂度 提升效率
全局变量自动初始化为0 局部变量为随机数
二维前缀和:O(nmq)->O(max(nm,q))因为查询是O(1) n行m列q个查询
公式推导及图解:https://www.acwing.com/solution/content/232751/
一维前缀和
#include<iostream>
using namespace std;
const int N = 1e5+10;
int a[N],s[N];
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i =1;i<=n;++i){
scanf("%d",&a[i]);
s[i] = s[i-1]+a[i];
}
int l , r;
while(m--){
scanf("%d%d",&l,&r);
printf("%d\n",s[r]-s[l-1]);
}
return 0;
}
二维前缀和
#include<iostream>
using namespace std;
const int N = 1e3+10;
int a[N][N],s[N][N];
typedef long long ll;
int main(){
int n,m,q;
scanf("%d%d%d",&n,&m,&q);
for(int i = 1;i<=n;++i)
for(int j = 1;j<=m;++j)
{
scanf("%d",&a[i][j]);
s[i][j] = s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];
}
while(q--){
int x1,x2,y1,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
ll res = s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1];
printf("%lld\n",res);
}
return 0;
}