AcWing 242. 一個簡單的整數問題
阿新 • • 發佈:2022-04-13
演算法分析
樹狀陣列(變型型別:差分)
樹狀陣列主要解決的是
1、a[x] += c
(單點修改)
2、求a[L ~ R]
(字首和)
本題要求求的是
1、a[L ~ R] += c
2、求a[x]
因為 字首和 和 差分 是一種逆運算,因此本題將原陣列a[]
轉換 差分陣列b[]
,就變成了樹狀陣列的模型
1、a[L ~ R] += c
等價於 b[L] += c,b[R + 1] -= c
2、求a[x]
等價於 求b[1 ~ x]
的字首和
注意:在求字首和時,要特別注意資料範圍,防止爆\(int\)
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int N = 100010; int n, m; int a[N]; //注意下這裡與標準模板的不同,因為求和可能會超過int上限,需要開long long // t[i]表示樹狀陣列i結點覆蓋的範圍和 LL t[N]; //返回非負整數x在二進位制表示下最低位1及其後面的0構成的數值 int lowbit(int x) { return x & -x; } //將序列中第x個數加上k void add(int x, int k) { for (int i = x; i <= n; i += lowbit(i)) t[i] += k; } //查詢序列前x個數的和 LL sum(int x) { int sum = 0; for (int i = x; i; i -= lowbit(i)) sum += t[i]; return sum; } int main() { cin >> n >> m; for (int i = 1; i <= n; i++) cin >> a[i]; //樹狀陣列初始化,儲存差分值 for (int i = 1; i <= n; i++) add(i, a[i] - a[i - 1]); while (m--) { char op; int l, r, d; cin >> op >> l; if (op == 'C') { //修改 cin >> r >> d; //差分,在l處加上d,在r+1位置減去d add(l, d), add(r + 1, -d); } else printf("%lld\n", sum(l)); //求字首和 } return 0; }