AcWing 797. 差分
差分
定义
给定一个原数组 \(a\),构造一个数组 \(b\),使得 \(a_i = b_1 + b_2 + b_3 + … + b_i\)。
也就是说,\(a\) 是 \(b\) 的前缀和数组,我们称 \(b\) 是 \(a\) 的差分数组。
换句话说,差分是前缀和的逆运算。
作用
在 \(O(1)\) 的时间复杂度内将序列中 \([l, r]\) 的一段区间内所有数加上 \(c\)(减法也一样)。
更具体些
构造差分数组
其实很简单:
//令 a[0] = 0
b[1] = a[1] - a[0];
b[2] = a[2] - a[1];
b[3] - a[3] - a[2];
...
b[n] = a[n] - a[n - 1];
重点!如何实现在 \(O(1)\) 的时间复杂度内将序列中 \([l, r]\) 的一段区间内所有数加上/减去 \(c\)
先放公式:
//这里是加上c的情况
b[l] += c;
b[r + 1] -= c;
为什么这样做?
b[l] += c;
:前面定义说了,\(a\) 是 \(b\) 的前缀和数组,所以只要改变 \(b_l\),\(a_l \sim a_n\) 都会跟着改变;b[r + 1] -= c;
:因为我们只需要改变 \(a_l \sim a_r\),\(a_{r + 1} \sim a_n\) 是多改变的,所以要让这一段 \(-c\)。
个人感觉有点类似于“后缀和”思想。
代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
const int N = 100010;
int a[N], b[N];
int main()
{
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i ++ )
{
scanf("%d", &a[i]);
b[i] = a[i] - a[i - 1]; // 预处理出差分数组
}
int l, r, c;
while (m -- )
{
scanf("%d%d%d", &l, &r, &c);
// 按上面的公式执行
b[l] += c;
b[r + 1] -= c;
}
for (int i = 1; i <= n; i ++ )
{
a[i] = b[i] + a[i - 1]; // 差分数组的前缀和是使原数组
printf("%d ", a[i]);
}
return 0;
}
另一种构造方式
上面讲了将 \([l, r]\) 区间内的所有数加 \(c\) 的公式:
b[l] += c;
b[r + 1] -= c;
假设开始时 \(a\) 数组都是 \(0\),所以 \(b\) 数组也都是 \(0\)。
如果我们要把 \(a_i\) 初始时设成 \(c\),其实可以看做在 \([i, i]\) 的这段区间中的数加 \(c\),代码如下:
b[i] += c;
b[i + 1] -= c;
第二种构造方式的代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
const int N = 100010;
int a[N], b[N];
// 这里把[l, r]区间加c的操作封装成一个函数
void insert(int l, int r, int c)
{
b[l] += c;
b[r + 1] -= c;
}
int main()
{
int n, m, l, r, c;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
for (int i = 1; i <= n; i ++ ) insert(i, i, a[i]); // 初始化差分数组
while (m -- )
{
scanf("%d%d%d", &l, &r, &c);
insert(l, r, c);
}
for (int i = 2; i <= n; i ++ ) b[i] += b[i - 1]; // b的前缀和就是a数组
for (int i = 1; i <= n; i ++ ) printf("%d ", b[i]);
return 0;
}
本文来自博客园,作者:FXT1110011010OI,转载请注明原文链接:https://www.cnblogs.com/FXT1110011010OI/p/16551251.html