差分是前缀和的逆运算
给定一个数组a[1],a[2] ···a[n],构造b[1],b[2]···b[n]满足a[i]=b[1]+b[2]+···+b[i],即a数组是b数组的前缀和
b[1]=a[1]
b[2]=a[2]-a[1]
b[3]=a[3]-a[2]
···
b[n]=a[n]-a[n-1]
b数组就称为a数组的差分,数组a就称为数组b的前缀和
给定一个区间[l,r],使a数组在[l,r]区间内所有数都加上c,只需b[l]+c,就会使a[l]+c,a[l+1]+c···a[n]+c。但是只想让a数组[l,r]区间内加上c,第r个数往后的数不加c,就需要打一个补丁即b[r+1]-c
差分的核心操作:将a[l,r]全部加上c,等价于b[l]+=c,b[r+1]-=c
效果:
1.a[1,l-1]无影响
2.a[l,r]加上c
3.a[r+1,n]无影响
作用:时间复杂度从O(n)变成O(1)
初始化:假定a数组全部是0,则b数组也全部是0;但实际a数组是有值的,可以看成是在0的基础上进行n步插入操作:在a[1,1]加上a[1],a[2,2]加上a[2],···,a[n,n]加上a[n]
题目:
代码:
#include<iostream>
using namespace std;
const int N=1e5+10;
int n,m;
int a[N],b[N];
//插入操作
void insert(int l,int r,int c){
b[l]+=c;
b[r+1]-=c;
}
int main(){
cin>>n>>m;
//a,b数组的初始化
for(int i=1;i<=n;i++)cin>>a[i],insert(i,i,a[i]);
while(m--){
int l,r,c;
cin>>l>>r>>c;
insert(l,r,c);
}
//a数组前缀和公式
for(int i=1;i<=n;i++)a[i]=a[i-1]+b[i],cout<<a[i]<<' ';
return 0;
}
有关算法竞赛的题目会继续更新,欢迎评论交流!