原题链接:
797. 差分 - AcWing题库
刚刚看了一道挺简单的题,手写暴力一下果然超时了。差分的效率果然是很高的。
类似于数学中的求导和积分,差分可以看成前缀和的逆运算。
差分数组:
首先给定一个原数组a:a[1], a[2], a[3],,,,,, a[n];
然后我们构造一个数组b : b[1] ,b[2] , b[3],,,,,, b[i];
使得 a[i] = b[1] + b[2 ]+ b[3] +,,,,,, + b[i]
也就是说,a数组是b数组的前缀和数组,反过来我们把b数组叫做a数组的差分数组。换句话说,每一个a[i]都是b数组中从头开始的一段区间和。
看题:
输入一个长度为 nn 的整数序列。
接下来输入 mm 个操作,每个操作包含三个整数 l,r,cl,r,c,表示将序列中 [l,r][l,r] 之间的每个数加上 cc。
请你输出进行完所有操作后的序列。
输入格式
第一行包含两个整数 nn 和 mm。
第二行包含 nn 个整数,表示整数序列。
接下来 mm 行,每行包含三个整数 l,r,cl,r,c,表示一个操作。
输出格式
共一行,包含 nn 个整数,表示最终序列。
数据范围
1≤n,m≤1000001≤n,m≤100000,
1≤l≤r≤n1≤l≤r≤n,
−1000≤c≤1000−1000≤c≤1000,
−1000≤整数序列中元素的值≤1000−1000≤整数序列中元素的值≤1000
输入样例:
6 3
1 2 2 1 2 1
1 3 1
3 5 1
1 6 1
输出样例:
3 4 5 3 4 2
话不多说直接上模板代码
#include
#include
#include
using namespace std;
const int N=100500;
int a[N],s[N];
int main()
{
int n,m;
cin>>n>>m;
for (int i = 1; i <= n; i ++ ) cin>>s[i];//存放数组
for (int i = 1; i <= n; i ++ ) a[i]=s[i]-s[i-1];//构建差分数组
while (m -- ){
int l,r,q;
cin>>l>>r>>q;
a[l]+=q;//将序列中[l, r]之间的每个数都加上q
a[r+1]-=q;//因为是区间是[l,r]所以到r+1的地方就要结束了
}
for (int i = 1; i <= n; i ++ ){
a[i]+=a[i-1];//前缀和运算一下
cout << a[i]<<" ";
}
}