前缀和:
前缀和:
s_arr[1]=arr[1];
s_arr[2]=arr[1]+arr[2];
s_arr[3]=arr[1]+arr[2]+arr[3];若要输出下标[l,r]的数组元素和就运用:s_arr[r]-s_arr[l-1]
#include<iostream> using namespace std; const int N = 11; //定义数组大小 int arr[N]; int s_arr[N]; //定义arr的前缀和数组 int main() { int n = 10; for (int i = 1; i <= n; i++) { cin >> arr[i]; s_arr[i] = s_arr[i - 1] + arr[i]; /* 前缀和: s_arr[1]=arr[1]; s_arr[2]=arr[1]+arr[2]; s_arr[3]=arr[1]+arr[2]+arr[3]; */ } for (int i = 1; i <= n; i++) cout << "arr[" << i << "]=" << arr[i]<<"\ts_arr[" << i << "]=" << s_arr[i] << endl; //若要输出下标[l,r]的数组元素和就运用:s_arr[r]-s_arr[l-1] int l = 3, r = 7; cout << s_arr[r] - s_arr[l - 1] << endl; return 0; }
差分:
差分:
Diff[1]=arr[1];
Diff[2]=arr[2]-arr[1];
Diff[3]=arr[3]-arr[2];差分数组的前缀和就是原数组
s_Diff[3] = Diff[1]+Diff[2]+Diff[3] = arr[1]+arr[2]-arr[1]+arr[3]-arr[2] = arr[3];#include<iostream> using namespace std; const int N = 11; //定义数组大小 int arr[N]; int Diff[N]; //定义arr的差分数组 int s_Diff[N]; //定义差分数组的前缀和数组 int main() { int n = 10; for (int i = 1; i <= n; i++) { cin >> arr[i]; Diff[i] = arr[i] - arr[i - 1]; //这就是差分的定义 /* 差分: Diff[1]=arr[1]; Diff[2]=arr[2]-arr[1]; Diff[3]=arr[3]-arr[2]; */ } /* 差分数组的前缀和就是原数组 s_Diff[3] = Diff[1]+Diff[2]+Diff[3] = arr[1]+arr[2]-arr[1]+arr[3]-arr[2] = arr[3]; 同理,前缀和数组的差分也就是原数组 */ for (int i = 1; i <= n; i++) s_Diff[i] = s_Diff[i-1] + Diff[i]; for (int i = 1; i <= n; i++) cout << "arr[" << i << "]=" << arr[i] << "\tDiff[" << i << "]=" << Diff[i] << "\ts_Diff[" << i << "]=" << s_Diff[i] << endl; return 0; }
例题:
#include <iostream> using namespace std; const int N = 1e5 + 9; typedef long long ll; //把long long 别名成ll ll arr[N]; ll chafen[N]; ll s[N]; ll ss[N]; int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); //加速否则时间过不去 ll n, m, q; cin >> n; for (ll i = 1; i <= n; i++) { cin >> arr[i]; //输入数组的数 chafen[i] = arr[i]-arr[i-1]; //定义arr的差分数组 } cin >> m; while (m--) { int l, r, x; cin >> l >> r >> x; chafen[l] += x; //将差分数组下标为[l]的+x chafen[r + 1] -= x; //将差分数组下标为[r+1]的-x } for (ll i = 1; i <= n; i++) s[i] = s[i - 1] + chafen[i]; //差分数组的前缀和数组(差分的前缀和就是原数组arr) for (ll i = 1; i <= n; i++) ss[i] = ss[i - 1] + s[i]; //原数组的前缀和 cin >> q; while (q--) { ll l, r; cin >> l >> r; cout << ss[r] - ss[l - 1] << "\n"; //要输入[l,r]的和,就输出前缀和数组ss[r]-ss[l-1] } return 0; }
对本题的:
chafen[l] += x; //将差分数组下标为[l]的+x
chafen[r + 1] -= x; //将差分数组下标为[r+1]的-x的解释:
假设a[ ]作为原数组,d[ ]作为原数组的差分数组。
若要是a[l]~a[r]的元素都+x,则只需要让d[l]+x,d[r+1]-x就行。
这样再对d[ ]求前缀和数组,即回到原数组,这时会发现,从a[l]~a[n]的元素都+x,而
a[r+1]~a[n]的元素都-x,这样一抵消,就剩下a[l]~a[r]的元素都+x。
差分与前缀和的联系
对原数组来说,其前缀和数组的差分数组就是原数组。
对原数组来说,其差分数组的前缀和数组就是原数组。