前缀和相关

十一.前缀和

一维

如果有一个长度为n的数组,前缀和数组Si表示为原数组中前i个数组的和。

注意前缀和中下标一定要从1开始。

1.如何求Si

①用for循环从i=1开始,S[i]=S[i-1]+a[i]

2.求Si的作用:可以快速的求出原数组中一段数的和。

二维(子矩阵的和)

S[i,j]的含义:从第1行到第i行的前j列的和。

1.如何去算?

一行行的去算。

S[i,j]=S[i-1,j]+S[i,j-1]-S[i-1,j-1]+a[i,j]可以画图思考,其中减去的部分是被加了两次的部分。

2.如果要求求以(x1,y1)为左上角,(x2,y2)为右下角的子矩阵的和,该如何去求?

①其总和为:S[x2,y2]-S[x1-1,y2]-S[x2,y1-1]+S[x1-1,y1-1]

此处可以画图理解,就是先算出大矩阵,然后减掉了两个小矩阵,最后加上一次 两次减法重合减去的部分

差分(前缀和的逆运算)

已知数组a,要求构造一个数组b,使得a[i]=b[1]+b[2]+……+b[i]

构造b[1]=a[1],则b[2]=a[2]-a[1]……b[n]=a[n]-a[n-1]

运用:

比如说一个题目要求把一个数组中[l,r]区间的数都加上C,如果用循环遍历时间复杂度为O(n),如果用拆分的话,构造完b,把b[l]加上C,再算a相当于a从l开始自动加上了C,时间复杂度为O(1),然后再让b[r+1]-C即可。

基于这个运用,也可以这样想:假设原数组a从1到n都为0,而实际上从[1,1]到[n.n]区间,每个区间都分别“插入”了a[1],a[2]……a[n],这样反推构造数组b,其实就相当于不用考虑如何去构造b了,详情见代码

给出一个数组长度n,接下来有m行,每行包括3个数据,分别shi l,r,c表示要在区间[l,r]中的每个数加上c

#include<iostream>
​
using namespace std;
​
const int N=10010;
​
int n,m;
int a[N].b[n];
​
void insert(int l,int r,int c){//负责插入的函数
    b[l]+=c;
    b[r+1]-=c;
}
​
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scnaf("%d",&a[i]);
    
    for(intg i=1;i<=n;i++) insert(i,i,a[i]);//这里是运用了加粗字体部分的思想正在构造差分数组b
    
    while(m--){
        int l,r,c;
        scanf("%d%d%d",&l,&r,&c);
        insert(l,r,c);
    }
    
    for(int i=1;i<=n;i++) b[i]+=b[i-1];//这里是为了把b数组变为自身的前缀和数组
    for(int i=1;i<=n;i++) printf("%d",b[i]);
}

二维差分(差分矩阵)

暂略

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值