差分

先来念一遍 差分数组 的定义:

这里 \(b\) 数组是 \(a\) 数组的差分数组。

首先给定一个原数组 \(a\)\(a_1, a_2, a_3 \ldots a_n\)

然后我们构造一个数组 \(b\)\(b_1, b_2, b_3 \ldots b_n\)

使得 \(a_i = b_1 + b_2+ b_3 + \ldots + b_i\)


我们需要构造差分数组。举个例子:\(n\) 等于 \(5\),则有:

\(a\)\(a_1, a_2, a_3, a_4, a_5\)

\(b\)\(b_1, b_2, b_3, b_4, b_5\)

\(a_1 = b_1\)
\(a_2 = b_1 + b_2\)
\(a_3 = b_1 + b_2 + b_3\)
\(a_4 = b_1 + b_2 + b_3 + b_4\)
\(a_5 = b_1 + b_2 + b_3 + b_4 + b_5\)

是不是很像三角形呢

所以稍微推理一下的:
\(b_1 = a_1\)
\(b_2 = a_2 - b_1 = a_2 - a_1\)
\(b_3 = a_3 - b_1 - b_2 = a_3 - a_1 - (a_2 - a_1) = a_3 - a_1 - a_2 + a_1 = a_3 - a_2\)
\(b_4 = a_4 - b_1 - b_2 - b_3 = a_4 - a_1 - (a_2-a_1)-(a_3-a_2)=a_4-a_1- a_2+a_1-a_3+a_2 = a_4 - a_3\)
\(\ldots\)

这里就不给大家枚举了。总感觉有点像分数列项呢 总之,我们总结出规律:\(b_i = a_i - a_{i - 1}\)

这就是构造差分数组的方法。


那么,怎么把差分摆在这道题目里呢?

简单:

  • 注:最后的答案就是差分数组 \(b\) 的前缀和。

\([l,r]\) 中的数加 \(c\),核心两句话:

  • b[l] += c;

既然最后的答案是 \(b\) 的前缀和,那么 \(b_l\) 加了 \(c\),就相当于 \(ans_{l \ldots n}\) 都加了 \(c\)

  • b[r + 1] -= c;

既然最后的答案是 \(b\) 的前缀和,那么 \(b_{r + 1}\) 减了 \(c\),就相当于 \(ans_{r + 1 \ldots n}\) 都减了 \(c\)

其中 \(ans_{l \ldots r}\) 加了 \(c\)\(ans_{r + 1 \ldots n}\) 加了 \(c\) 又减了 \(c\),等于啥也没发生。我们的目的达到了!


代码:

#include <iostream>
#include <cstdio>
using namespace std;
int n,m;
int a[100010],b[100010];
int main() {
	scanf("%d%d",&n, &m);
	for (int i = 1; i <= n; i ++ ) {
		scanf("%d",&a[i]);
		b[i] = a[i] - a[i-1];//构造差分数组。 
	} 
	while (m -- ) {
		int l, r, c;
		scanf("%d%d%d",&l, &r, &c);
		b[l] += c; b[r + 1] -= c;
	}
	for (int i = 1; i <= n; i ++ )
		b[i] = b[i - 1] + b[i];
	for (int i = 1; i <= n; i ++ )
		printf("%d ",b[i]);
	return 0; 
}

您看得那么认真,点个宝贵的赞👍再走吧!谢谢各位路过的神犇!

posted @ 2022-02-04 16:45  福宝j  阅读(74)  评论(0编辑  收藏  举报