前缀和 与 差分

前缀和:

前缀和:
s_arr[1]=arr[1];
s_arr[2]=arr[1]+arr[2];
s_arr[3]=arr[1]+arr[2]+arr[3];

若要输出下标[l,r]的数组元素和就运用:s_arr[r]-s_arr[l-1]

#include<iostream>
using namespace std;
const int N = 11;	//定义数组大小
int arr[N];
int s_arr[N];		//定义arr的前缀和数组
int main()
{
	int n = 10;
	for (int i = 1; i <= n; i++)
	{
		cin >> arr[i];
		s_arr[i] = s_arr[i - 1] + arr[i];
		/*
		前缀和:
		s_arr[1]=arr[1];
		s_arr[2]=arr[1]+arr[2];
		s_arr[3]=arr[1]+arr[2]+arr[3];
		*/
	}
	for (int i = 1; i <= n; i++)
		cout << "arr[" << i << "]=" << arr[i]<<"\ts_arr[" << i << "]=" << s_arr[i] << endl;
	//若要输出下标[l,r]的数组元素和就运用:s_arr[r]-s_arr[l-1]
	int l = 3, r = 7;
	cout << s_arr[r] - s_arr[l - 1] << endl;
	
	
	return 0;

}

差分:

差分:
Diff[1]=arr[1];
Diff[2]=arr[2]-arr[1];
Diff[3]=arr[3]-arr[2];

差分数组的前缀和就是原数组
s_Diff[3] = Diff[1]+Diff[2]+Diff[3] = arr[1]+arr[2]-arr[1]+arr[3]-arr[2] = arr[3];

#include<iostream>
using namespace std;
const int N = 11;	//定义数组大小
int arr[N];
int Diff[N];		//定义arr的差分数组
int s_Diff[N];		//定义差分数组的前缀和数组
int main()
{
	int n = 10;
	for (int i = 1; i <= n; i++)
	{
		cin >> arr[i];
		Diff[i] = arr[i] - arr[i - 1];			//这就是差分的定义
		/*
		差分:
		Diff[1]=arr[1];
		Diff[2]=arr[2]-arr[1];
		Diff[3]=arr[3]-arr[2];
		*/
	}
	/*
	差分数组的前缀和就是原数组
	s_Diff[3] = Diff[1]+Diff[2]+Diff[3] = arr[1]+arr[2]-arr[1]+arr[3]-arr[2] = arr[3];
	同理,前缀和数组的差分也就是原数组
	*/
	for (int i = 1; i <= n; i++)
		s_Diff[i] = s_Diff[i-1] + Diff[i];
	for (int i = 1; i <= n; i++)
		cout << "arr[" << i << "]=" << arr[i] << "\tDiff[" << i << "]=" << Diff[i] << "\ts_Diff[" << i << "]=" << s_Diff[i] << endl;
	return 0;

}

例题:

P1050 - 【模板】差分 - ETOJ

#include <iostream>
using namespace std;
const int N = 1e5 + 9;
typedef long long ll;		//把long long 别名成ll
ll  arr[N];
ll chafen[N];
ll s[N];
ll ss[N];
int main()
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);	//加速否则时间过不去
	ll n, m, q;
	cin >> n;
	for (ll i = 1; i <= n; i++)
	{

		cin >> arr[i];			//输入数组的数
		chafen[i] = arr[i]-arr[i-1];		//定义arr的差分数组
	}
	cin >> m;
	while (m--)
	{
		int l, r, x;
		cin >> l >> r >> x;
		chafen[l] += x;		//将差分数组下标为[l]的+x
		chafen[r + 1] -= x;	//将差分数组下标为[r+1]的-x
	}
	for (ll i = 1; i <= n; i++)
		s[i] = s[i - 1] + chafen[i];	//差分数组的前缀和数组(差分的前缀和就是原数组arr)
	for (ll i = 1; i <= n; i++)
		ss[i] = ss[i - 1] + s[i];		//原数组的前缀和
	cin >> q;
	while (q--)
	{
		ll l, r;
		cin >> l >> r;
		cout << ss[r] - ss[l - 1] << "\n";		//要输入[l,r]的和,就输出前缀和数组ss[r]-ss[l-1]
	}


	return 0;
}

对本题的:

        chafen[l] += x;        //将差分数组下标为[l]的+x
        chafen[r + 1] -= x;    //将差分数组下标为[r+1]的-x

的解释:

          假设a[ ]作为原数组,d[ ]作为原数组的差分数组。

        若要是a[l]~a[r]的元素都+x,则只需要让d[l]+x,d[r+1]-x就行。

          这样再对d[ ]求前缀和数组,即回到原数组,这时会发现,从a[l]~a[n]的元素都+x,而

        a[r+1]~a[n]的元素都-x,这样一抵消,就剩下a[l]~a[r]的元素都+x。

差分与前缀和的联系

对原数组来说,其前缀和数组的差分数组就是原数组。

对原数组来说,其差分数组的前缀和数组就是原数组。

参考:

【C++算法基础】#9前缀和与差分 | 轻松学算法 | 图解ACM竞赛算法_哔哩哔哩_bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值