前缀和与差分

前缀和
在这里插入图片描述

/**
     * 一维前缀和
     *
     * @a 表示原数组
     * @sum 表示a数组的一维前缀和
     */
     const int maxn = 1e5 + 10;
     int a[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; 
     int sum[maxn];
    void oneDimen(int num) {//num表示数组a的长度
        sum[0] = a[0];
        for (int i = 1; i < num; i++) {
            sum[i] = sum[i - 1] + a[i];
        }
    }
s[0]=0;
s[i]=a[1]+a[2]+a[3]+...+a[i];

for(int i=1;i<=n;i++)
s[i]=s[i-1]+a[i];//前缀和的初始化 


[l,r]的和
s[r]-s[l-1];//区间和的计算 

在这里插入图片描述

const int maxn = 1e5 + 10;
int a[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; 
int diff[maxn];
//求出差分数组
void chafen(int num){//num表示原数组的长度
	diff[0] = a[0];
	for(int i = 1; i < num; i++){
		diff[i] = a[i] - a[i - 1];
	}
}
//对区间进行加操作
void addarray(int L, int R, int k){
	//L和R分别代表对加区间的左右范围,k表示在区间里每个元素加的数字
	diff[L] += k;
	diff[R + 1] -= k;//这里特别要注意,因为在前面进行区间加后,后面一个数与前面这个数的差变小了,所以要在后面这个数的差分数组减去前面区间所增加的数字。
}
//通过差分数组和原数组a推理得到进行区间加后数组中某一个元素的值
void get_a(){
	for(int i = 1; i <= n; i++){
		a[i] = doff[i] + a[i - 1];
	} 
}

差分就是将数列中的每一项分别与前一项数做差,例如:
一个序列1 2 5 4 7 3,差分后得到1 1 3 -1 3 -4 -3

这里注意得到的差分序列第一个数和原来的第一个数一样(相当于第一个数减0)

差分序列最后比原序列多一个数(相当于0减最后一个数)

性质:

1、差分序列求前缀和可得原序列

2、将原序列区间[L,R]中的元素全部+1,可以转化操作为差分序列L处+1,R+1处-1

3、按照性质2得到,每次修改原序列一个区间+1,那么每次差分序列修改处增加的和减少的相同

二维前缀和

 /**
     * 二维前缀和
     *
     * @param src 原数组
     * @return 二维前缀和
     */
     const int maxn = 100;
     int prefixSum[maxn][maxn];
    void twoDimen(int a[][], int n, int m) {//n和m分别代表二维原始数组的行列长度
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (i == 0 && j == 0) {//第0个,最左上角
                    prefixSum[i][j] = a[i][j];
                } else if (i == 0) {//第一行,最顶部一行
                    prefixSum[i][j] = prefixSum[i][j - 1] + a[i][j];
                } else if (j == 0) {//第一列,最左边一列
                    prefixSum[i][j] = prefixSum[i - 1][j] + a[i][j];
                } else {//其他
                    prefixSum[i][j] = prefixSum[i - 1][j] + prefixSum[i][j - 1] + a[i][j] - prefixSum[i - 1][j - 1];
                }
            }
        }
    }

i == 0 && j ==0,只有一个直接赋值即可:prefixSum[0, 0] = a[0, 0]。
i == 0,最左边的一列,二维前缀和为元素上一行相同列的元素加该数字,公式为prefixSum[0, j] = prefixSum[0, j-1] + a[0, j];
j == 0,最上面一排,与i == 0类似prefixSum[i, o] = prefixSum[i-1, 0] + a[i, 0];
i!=0 || j!=0,其公式为 prefixSum[i][j] = prefixSum[i - 1][j] + prefixSum[i][j - 1] + a[i][j] - prefixSum[i - 1][j - 1];
其代码模板如下所示

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值