前缀和与差分

前缀和与差分

1. 一维前缀和

前缀和(Prefix Sum)的定义为:对于一个给定的数列A,它的前缀和数列S是通过递推能求出来S[i]=数组A下标从1到i的部分和。

例如:
A[5, 6,7,8]= PrefixSum[5,11,18,26]
PrefixSum[0]= A[0]=0
PrefixSum[]= A[0]+ A[1]=0+5=5
PrefixSum[2] = A[0]+ A[1]+ 4[2]= Pr efixSum[1]+ A[2]=5+6=11
PrefixSum[3]= A[0]+ A[1]+ A[2]+ A[3]= PrefixSum[2]+ A[3]=11+7=18
PrefixSum[4]= A[0]+ A[1]+ A[2]+ A[3]+ 4[4]= PrefixSum[3]+ A[4]=18+8= 26

  • C++实现一维前缀和
const int MAXN = 1e5+4;//定义数组个数
int nums[MAXN]={};//nums数组保存原始数据,并初始化为0
int sums[MAXN]={};//sums为前缀和数组
//nums[0]=0;sums[0]=0;
cin>>n;
for (int i=1; i<=n; i++){
	cin >> nums[i];
	sums[i]=sums[i-1]+a[i];
}
  • 一维前缀和有什么用

输入一个长度为n的整数序列。接下来再输入m个询问,每个询问输入一对l、r,对于每个询问,输出原序列中从第l个数到第r个数的和。降低时间复杂度。

2. 二维前缀和

定义一个矩阵a,则二维前缀和为:sum[i][j] = i行j列的二维数组的元素和。
例如,我们有这样一个矩阵
1 2 4 3
5 1 2 4
6 3 5 9

该矩阵的二维前缀和为
1 3 7 10
6 9 15 22
12 18 29 45

  • C++实现二维数组和
const int MAXN = 1e3+2; const int MAXM=1e3+2;
int sums[MAXN][MAXM]={};//sums为前缀和数组
int n,m;
cin>>n>>m;//读入矩阵的维度
for (int i=1; i<=n; i++){
	for (int j=1; j<=m; j++) {
		int x; 
		cin>> X;
		sums[i][j]=sums[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+X;
	}
}
  • 二维前缀和有什么用
    输入一个n行m列的整数矩阵,再输入q个询问,每个询问包含四个整数x1,y1,x2,y2,表示一个子矩阵的左上角坐标和右下角坐标。对于每个询问输出子矩阵中所有数的和。

3. 一维差分
差分定义:一个数列a,则相邻两个数的差构成的序列就是差分序列p.即p[i] = a[i] - a[i-1].

  • 差分的应用
    例如数列a={1,2,3,3,3,3},则对应的差分数列p={1,1,1,0,0,0}。给数列a的[3, 5]加上首项为2公差为k=1的等差数列,也就是{2,3,4}, 那么对应的a变为{1,2,5,6,7,3},对应的差分数列p变为{1,1,3,1,1,-4}。说明
    p[r]=p[r]+k,p[r+1] = p[r+1] - k,最后对p[l,r]做一次前缀和。

  • 例题
    输入一个长度为n的整数序列。
    接下来输入m个操作,每个操作包含三个整数|, r, c,表示
    将序列中[|,r]之间的每个数加上C。
    请你输出进行完所有操作后的序列。

下面我们根据样例输入来分析一下,样例输出是如何得到的。
初始数组a为3 1 1 -2 1 -2 -1
初始状态的差分数组diff为1 1 0 -1 1 -1。
第一次操作为1 3 1,那么就是diff[1] = diff[1]+1,diff[4] = diff[4]-1,得到
差分数组diff变为210-21-1。
第二次操作为3 5 1,那么就是diff[3] = diff[3]+1,diff[6] = diff[6]-1,得到
差分数组diff变为2 1 1 -2 1 -2。
第三次操作为1 6 1,那么就是diff[1] = diff[1]+1,diff[7] = diff[7]-1,得到
差分数组diff变为3 1 1 -2 1 -2 -1。

因此,最终的原始差分数组如下:
3 1 1 -2 1 -2 -1
再进行一次前缀和得:
a[1] = diff[0]+diff[1]= 3
a[2] = diff[0]+diff[1]+diff[2] =4
a[3] = diff[0]+diff[1]+diff[2]+diff[3] = 5
a[4] = diff[0]+diff[1]+diff[2]+diff[3]+diff[4] = 3
a[5] = diff0]diff[1]f2l]iff[1]jiff4]+diff[5] = 4
a[6] = diff[0]+diff[1]+diff[2]+diff[3]+diff[4]+diff[5]+diff[6] = 2

4. 二维差分

二维差分是二维前缀和逆运算。

在这里插入图片描述矩阵a为:
1 2 4 3
5 1 2 4
6 3 5 9
对应的二维差分矩阵p为
1 1 2 -1
4 -5 -1 3
1 1 1 2

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值