无论前缀和还是差分法,目的都是为了尽可能不要出现双重循环,通过数学技巧降低时间复杂度。
前缀和:计算l,r区间内的元素和,第一反应是使用循环累加区间内的每个元素,
而前缀和则牺牲空间创建summ(n+1)数组,在得到元素值时顺便记录前缀和,将累加区间元素的循环降维成summ[r]-summ[l] 一句代码,时间复杂度从循环直接变成常数;
差分:将l,r区间内元素都加上k,第一反应同样是使用循环遍历区间内的每个元素进行变化,
而差分则是牺牲空间创建d(n+2)数组,在得到元素值时顺便记录差值,将改变区间元素的循环降维成d[r+1]-=k,d[l]+=k两句话,时间复杂度从循环直接变成常数。
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
vector<long long> s(n+1);
vector<long long> d(n+2,0); // n+2:假如r=n,那么d[r+1]=n+2,防止越界
for (int i = 1; i <= n; i++) {
cin >> s[i];
d[i] = s[i] - s[i-1];
}
while (m--) {
long long l, r, k;
cin >> l >> r >> k;
d[l] += k;
d[r+1] -= k;
}
for (int i = 1; i <= n; i++) {
s[i] = s[i-1] + d[i];
cout << s[i] << " ";
}
}

京公网安备 11010502036488号