C/C++ 前缀和与差分
个人主页:仍有未知等待探索_C语言疑难,数据结构,算法-CSDN博客
专题分栏:算法_仍有未知等待探索的博客-CSDN博客
目录
一、前言
1、什么是前缀和
2、什么是差分
3、优势
1.朴素做法:
2.用差分数组
二、代码实现
1、给一个数组去求其差分数组
2、给一个数组去求其前缀和数组
一、前言
1、什么是前缀和
前缀和是一种预处理,用于降低查询时的时间复杂度。其就像是数学中的前n项和。
给定 n个整数,然后进行 m 次询问,每次询问求一个区间内值的和。
如果用暴力写法,那每次询问都需要从区间左端点循环到区间右端点求和,时间复杂度较大。
这种时候就可以预先求出该数组的一维前缀和。
比如说数组【1,1,1,1,1】,则前缀和数组就是【1,2,3,4,5】。
2、什么是差分
差分更像是前缀和数组的原数组。
比如说前缀和数组是【1,2,3,4,5】,则差分数组就是【1,1,1,1,1】。
总结一句话:前缀和和差分是互逆运算。
3、优势
如果让你把数组的一个子区间全都加上一个数 c,并且去对改区间进行求和。
1.朴素做法:
- 找到该区间,然后对每个数进行相加 c
- 在遍历一遍进行求和
如果要加数的区间多,求和的区间多的话,时间太长。
2.用差分数组
- 找到要加数的区间左端点,然后仅对左端点进行加 c 操作(在左端点的右侧,其前缀和数组均加上了 c)
- 但是我们想加数的范围仅在某一个区间,这样的话我们就对其右端点+1进行-c操作,这样就行了
二、代码实现
注意:数组一定要从1开始进行存储,要不然求前缀和数组的时候还要特判。
1、给一个数组去求其差分数组
#include<iostream>
using namespace std;
const int N = 1e5 + 5;
int a[N];//原数组
int b[N];//差分数组
int n;//数的个数
//可以将求一个差分数组,分成求1个元素的差分数组
void insert (int c,int i)
{
b[i] += c;
b[i + 1] -= c;
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) insert(a[i], i);
for (int i = 1; i <= n; i++) cout << b[i] << " ";
return 0;
}
2、给一个数组去求其前缀和数组
#include<iostream>
using namespace std;
const int N = 1e5 + 5;
int n;//数的个数
int a[N];//原数组
int s[N];//前缀和数组
int main() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) {
s[i] = s[i - 1] + a[i];//每一个前缀和数组元素一定是它前一个前缀和数组元素加上自己的元素
}
for (int i = 1; i <= n; i++) {
cout << s[i] << " ";
}
return 0;
}
谢谢大家的支持!