5.6前缀和数组

本文介绍了如何在读取过程中计算一维和二维数组的前缀和数组,通过递推公式(s[i]=s[i-1]+a[i])和特定边界条件,快速求解任意区间内元素之和。同时提及了其他类型的前缀和数组定义及其计算方法。
摘要由CSDN通过智能技术生成

1.一维数组的前缀和数组

假设有n个整数a1,a2,…,an,存储在数组a中,从第1个元素开始存储设前缀和数组为s,则s[i]=a[1]+a[2]+…+a[i-1]+a[i],如下图所示
易知s[i]=s[i-1]+a[i],s[1]=a[1]

可以在读入n个整数到数组a的同时求出前缀和数组为了使得s[1]可以统一处理需要从第1个元素开始存储数据,且将s[0]设置为0。这样,s[1]=s[0]+a[1]
引入前缀和数组的目的是快速求出数列中一段数的和。例如,第p个至第q个数的和(q≥p≥1)为:s[q]-s[p-1]

int a[1010], s[1010] = {0};
int n; cin >> n;
for(int i=1;i<=n;i++){
    cin >> a[i];
    s[i] = s[i-1] + a[i];
} 

2.二维数组的前缀和数组

对二维数组a,也可以定义二维前缀和数组s。s[i][j]为第1行到第i行、第1列到第j列之间的那些元素之和,即图(a)中阴影部分的元素之和
s[i][j]的递推公式为:
s[i][j] = s[i][j-1] + s[i-1][j] - s[i-1][j-1] + a[i][j]
s[1][j] = s[1][j-1] + a[i][j],s[1][j]为第1行的元素
s[i][1] = s[i-1][1] + a[i][j],s[i][1]为第1列的元素 
 

其中s[i][j-1]为s[i][j]左边的元素,如图(b)所示;s[i-1][j]为s[i][j]正上方的元素,如图(c)所示;这两项的和有一部分元素和重复统计了,就是s[i-1][j-1],如图(d)所示,所以要减去再加上a[i][j],得到的结果就是s[i][j]

 同样,可以在读入数组a的元素a[i][j]的同时求出前缀和数组。为了使得第1行和第1列的元素可以统一处理,需要从数组的第1行、第1列开始存储数组元素,且将s数组的第0行和第0列设置为0

int a[1010][1010], s[1010][1010] = {0};
int n, m; cin >> n >> m;
for(int i=1;i<=n;i++){
    for(int j=1;j<=m;j++){
        cin >> a[i][j];
        s[i][j] = s[i][j-1] + s[i-1][j] - s[i-1][j-1] + a[i][j];
    }
}

求出二维前缀和数组s后,可以快速求出数组a第r1行到第r2行、第c1列到第c2列之间所有元素的和,即下图中阴影部分的元素之和,求得的结果为:

s[r2][c2]-s[r2][c1-1]-s[r1-1][c2]+s[r1-1][c1-1]

其中,s[r2][c2]为数组第1行到第r2行、第1列到第c2列之间所有元素的和。类似地,易知s[r2][c1-1]、s[r1-1][c2]和s[r1-1][c1-1]的含义。s[r2][c2]减去s[r2][c1-1]、s[r1-1][c2]这两项后,有一部分元素减去了两遍,要加回来,这部分元素之和就是s[r1-1][c1-1]

3.其他前缀和数组

根据求解问题的需要,也可以定义其他前缀和数组。例如,对二维数组,可以将前缀和数组元素s[i][j]定义为第列第1行到第i行这部分元素的和,即s[i][j] = a[1][j] + … + a[i][j]。求s[i][j]的递推公式为:s[i][j-1]=s[i][j-1]+a[i][j]。可以用以下代码在读入数组的元素的同时求出前缀和数组 

int a[1010][1010], s[1010][1010] = {0};
int n, m; cin >> n >> m; //n行m列
for(int i=1;i<=n;i++){
    for(int j=1,j<=m;j++){
        cin >> a[i][j];
        s[i][j] = s[i][j-1] + a[i][j];
    }
}
  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值