D4.前缀和、差分

前缀和

一维前缀和(区间)

在这里插入图片描述

  • 这样的好处是,可以以O(1)的时间复杂度来计算。而不是遍历O(n)
  • 当读入数据非常大(>1000000)的时候,建议使用scanf()来读取数据,会比cin >> 快很多。
  • 在全局开数组的时候比如A[100][100];a[10010]不必手动定义下标0的元素为0,因为初始化之后所有元素的值均为0.
  1. 递推公式(前缀和的初始化
    读入数组a[N]之后,前缀和的初始化
for(int i = 1; i <= n; i ++)
	S[i] = S[i - 1] + a[i];
  1. 任意连续区间 [l, r]部分和
部分和
= S[r] - S[l-1]
= a[l] + a[l+1] + ... + a[r]

例如,求区间[1,10]区间的和,就是 S[10] - S[0]

二维前缀和(子矩阵)

在这里插入图片描述

这个定义方式和循环有关。。

  1. 递推公式(前缀和的初始化
    在这里插入图片描述
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] + a[i][j];
  1. 子矩阵元素的和(部分和
    在这里插入图片描述

下标为1都-1
公式:

S[x1,y1][x2,y2] = S[x2,y2] - S[x1-1,y2] - S[x2,y1-1] + S[x1-1,y1-1]

综合运用 步骤

在这里插入图片描述

差分

一维差分

在这里插入图片描述

作用:

  1. .对数组a[] 求一遍前缀和就可以得到数组S[] O(n)
  2. 使得已知原数组S[] 在区间 [l, r] 上实现:S[l]+c, S[l+1]+c...S[r]+c
    只需要a[l]+c; a[r+1]+c
    在这里插入图片描述

注意,如果使用暴力做法,时间复杂度是 O(n),使用差分数组,时间复杂度是 O(1)

综合运用 步骤

在这里插入图片描述

  • 具体的insert()函数 初始化差分数组的原理就是利用a[n] = S[n] - S[n-1]:
    在这里插入图片描述

  • 读入已知数组S[];利用insert()函数初始化差分数组a[];根据请求修改差分数组;之后求出修改后对应的答案数组S[],有两种方法:
    1)使用递推公式修改原数组S[]

for(int i = 1; i <= n; i ++)
	S[i] = S[i-1] + a[i];

2)直接把差分数组改成答案数组
好吧,就像是直接拿a[]空间来储存S[]的样子…

for(int i = 1; i <= n; i ++)
	a[i] = a[i-1] + a[i]

<##>一般前缀和的实际用处<##>

  1. 关于字符串,需要使用str[N]来读入,注意读入差分数组是从下标1开始存入的,所以要scanf("%d", str+1);并且这个时候就不要使用取地址符号&了。
  2. 除了O(n)计算区间的部分和,前缀和还可以统计一段字符串中某个字符a出现的次数。初始化字符串之前,字符== a;那么赋值为1,否则为0。这个时候一般要开二维数组A[i][j] ,使用i来区分不同的数组,然后str[j] - 'A' / str[j] - 'a'来进行比较…再初始化前缀和数组。
  3. 有的题目还是根据题干信息进行寻找潜在的前缀和雏形。

二维差分(差分矩阵)

1)让a[]的子矩阵范围(x1,y1->x2,y2)内的每一个数据都加+c,只需要处理差分矩阵的四个元素即可。
2)差分矩阵开始的初始化也是通过insert()函数来实现。
3)最后求出修改后的答案数组,就是求一下修改后的a[]的前缀和就好。
在这里插入图片描述

关于思路解释

一开始假设前缀和数组S[]中的元素都是0,那么对应的差分数组a[]中元素也都是0—这就满足了前缀和数组恶和差分数组的对应关系。insert()函数实现的功能是使S[]特定区间上的元素S[i]都+c,使用for循环逐个insert(i,i,S[i]),逐一插入S[i]那么就构造出了已知的前缀和数组S[]。至于insert()内部对于差分数组a[]的改动,是基于可以保持a[]是S[]的差分数组这一条件下的,所以在构建完S[]数组的同时a[]也完成了构建。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值