差分
给定长度为n的序列,有m个更新,每次更新要求使[l, r]范围内的数增加c,给出最后的序列。
朴素思想当然是直接一个循环使得[l, r]范围内的数直接都加c,但是这样做的话复杂度是O(nm)。
如果我们能用O(1)的操作来完成每一次的更新就好了。
所以引入差分序列:设有序列sub[],sub[i] = a[i] - a[i - 1]。
差分和前缀和互为逆操作,我们只要最后在对sub序列做一次前缀和就可以得到原序列。
在差分序列中更新一个数是会影响到恢复序列的这个数以后的所有数的,这个影响被放大了。
如果我们要给[l, r]加上c,那么我们只要sub[l] += c, sub[r + 1] -= c;
制作差分序列和前缀和一样,并不需要新建数组,只需要倒序遍历原数组就可以原地创建差分数组,当然也可以通过保留前一个值的方案在读取的时候就完成创建。
以下分别给出两种创建方案。
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int a[N];
int main(){
int n,m,l,r,c;
cin >> n >> m;
for(int i = 1;i <= n; i++)cin >> a[i];
for(int i = n; i > 1; i--)a[i] -= a[i - 1];
while(m--){
cin >> l >> r >> c;
a[l] += c;
a[r + 1] -= c;
}
for(int i = 1;i <= n; i++){
a[i] += a[i - 1];
cout << a[i] << " ";
}
cout << endl;
}
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int a[N];
int main(){
int n,m,l,r,c,last,t;
cin >> n >> m;
cin >> last, a[1] = last;
for(int i = 2;i <= n; i++){
cin >> t;
a[i] = t - last;
last = t;
}
while(m--){
cin >> l >> r >> c;
a[l] += c;
a[r + 1] -= c;
}
for(int i = 1;i <= n; i++){
a[i] += a[i - 1];
cout << a[i] << " ";
}
cout << endl;
}