差分可以说是前缀和的逆运算了
假设给你一个数组:arr[n] = {1,4,6,-1,8,...}
给你m个操作:每次操作给你l,r,val,让你对数组l~r区间内的数都加上一个val
朴素的做法(单次操作):
for(int i = l,i<=r;i++)
arr[i]+=val;
时间复杂度为 r-l+1
这样算下来整体的时间复杂度很大
当朴素的暴力T的时候,就需要引进差分这一算法
正如我开头说的:差分是前缀和的逆运算
我们如何理解这句话呢?
随便举一个例子:
有一个数组:arr--> 1 7 8 -19 22
我们引进一个差分数组cf
接下来请您认真看:
arr 1 7 8 -19 22
ch 1 6 1 -27 41
引进一个前缀和sum_ch数组
sum_ch 1 7 8 -19 22
是不是神奇的发现:arr == sum_ch
所以,差分就是前缀和的逆运算
如何实现差分?
如果你理解了上面,那你绝对可以理解下面的内容了!!!
for(int i = 1;i<=n;i++)
cin>>arr[i];
arr为原数组
接下来是把arr差分化操作:
----------------------
for(int i = 1;i<=n;i++)
cf[i] = arr[i] - arr[i-1]//差分是前缀和的逆运算
//arr[0] = cf[0] = 0(开全局变量,初始化为全0)
----------------------
接下来是某些操作了,还是按文章最开始的,给你l,r,val,让你对区间l~r数组中的数加上一个val
----------------------
cf[l] += val;
cf[r+1] += val;
就是如此的简单
----------------------
接下来就是输出操作后的数据了
----------------------
int sum = 0;
for(int i = 1;i<=n;i++)
{
sum+=cf[i];
cout<<sum<<' ';
}
cout<<endl;
----------------------
(完)
接下来是一道非常板的题:
AC代码如下:
#include<iostream>
#include<cstring>
using namespace std;
const int N = 1e5+9;
int s[N],cf[N];
int main()
{
int n,m;
cin>>n>>m;
for(int i = 1;i<=n;i++)
{
cin>>s[i];
cf[i] = s[i]-s[i-1];
}
while(m--)
{
int l,r,vis;
cin>>l>>r>>vis;
cf[l]+=vis;
cf[r+1]-=vis;
}
int ans = 0;
for(int i = 1;i<=n;i++)
{
ans+=cf[i];
cout<<ans<<' ';
}
cout<<endl;
}
最后,感谢您的阅读!!!