- [[#差分陣列|差分陣列]]
- [[#差分陣列#三個陣列的關係|三個陣列的關係]]
- [[#題目描述|題目描述]]
- [[#輸入描述|輸入描述]]
- [[#輸出描述|輸出描述]]
- [[#輸入樣例1|輸入樣例1]]
- [[#輸出樣例1|輸出樣例1]]
差分陣列
- 如下叫做差分陣列
\[d_{i} = a_{i} - a_{i-1}
\]
- 又有
\[\sum_{j=1}^{i} {d_{j}} = d_{1}+d_2+\dots+d_i
\]
- 而上述式子可以寫作
\[d_{1}+d_2+\dots+d_{i}= (a_1-a_{0})+(a_2-a_1)+\dots+(a_{i-1}-a_{i-2})+(a_i-a_{i-1})
\]
- 又因為 \(a_0=0\) 於是上式(左側為一個字首和陣列)
\[\sum_{j=1}^{i} {d_{j}}=a_i
\]
- 差分陣列可以實現字尾區間的修改,是靜態的修改(修改完成之後進行詢問,不可以邊詢問邊修改)
- 如果對 \(d_2\) 增加了 \(x\) ,那麼 \(a_{2}、a_{3}、a_4\) 以後都會增加 \(x\) ,那麼當在 \(d_4\) 處減少 x 後,就抵消了從 \(d_4\) 開始往後的修改,做到了只在 \(a_{2}、a_3\) 兩個位置的修改(增加x)
三個陣列的關係
-
題目書寫模板
-
讀入陣列 => 求出差分陣列 => 修改差分陣列 => 更新原陣列 => 求出字首陣列 => 列印結果
題
題目描述
給定一個長度為n的陣列a,和兩個整數p,q。
先進行p次區間加操作:將區間[l,r]的數字都加上�x。
再進行q次區間查詢操作:求出[l,r]的數字之和。
對於每次區間查詢操作,輸出結果。
輸入描述
第一行三個整數 n,p,q。(1≤n≤105,0≤p≤105,0≤10^5≤q)
第二行 n 個整數表示陣列 a。(−109≤a_i≤109)
接下來 p 行,每行三個整數 l,r,x。(1≤l≤r≤n,−109≤x≤109)
接下來q行,每行兩個整數l,r。(1≤l≤r≤n)
輸出描述
對於每次區間查詢操作,輸出結果。
輸入樣例1
5 1 2
1 1 1 2 2
1 4 2
1 3
1 5
輸出樣例1
9
15
Code
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5 + 9;
// 全域性陣列自動初始化為0
ll a[N], prefix[N], diff[N];
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, p, q;
cin >> n >> p >> q;
for (int i = 1; i <= n; ++i) cin >> a[i];
for (int i = 1; i <= n; ++i) diff[i] = a[i] - a[i - 1];
while (p--) {
int l, r;
ll x;
cin >> l >> r >> x;
diff[l] += x, diff[r + 1] -= x;
}
// 更新a
for (int i = 1; i <= n; ++i) a[i] = a[i - 1] + diff[i];
// prefix
for (int i = 1; i <= n; i++) prefix[i] = prefix[i - 1] + a[i];
while (q--) {
int l, r;
cin >> l >> r;
cout << prefix[r] - prefix[l - 1] << '\n';
}
return 0;
}