Acwing 243. 一個簡單的整數問題2 —— 差分樹狀陣列(複雜引用版本)
阿新 • • 發佈:2020-12-29
題目連結:https://www.acwing.com/problem/content/244/
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 6 using namespace std; 7 8 typedef long long LL; 9 const int N = 100010; 10 int a[N]; 11 LL tr1[N]; //維護b[i]的差分陣列 12 LL tr2[N]; //維護 i * b[i] 的差分陣列13 int n, m; 14 15 int lowbit(int x) 16 { 17 return x & -x; 18 } 19 20 int add(LL tr[], int x, LL k) 21 { 22 for (int i = x; i <= n; i += lowbit(i)) tr[i] += k; 23 } 24 25 LL sum(LL tr[], int x) 26 { 27 LL res = 0; 28 for (int i = x; i ; i -= lowbit(i)) res += tr[i]; 29 returnres; 30 } 31 32 LL per_sum(int x) 33 { 34 return sum(tr1, x) * (x + 1) - sum(tr2, x); 35 } 36 37 int main() 38 { 39 scanf("%d%d", &n, &m); 40 for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]); 41 42 for (int i = 1; i <= n; i ++ ) 43 { 44 int x = a[i] - a[i - 1]; 45 add(tr1, i, x); add(tr2, i, (LL)x * i); 46 } 47 48 while (m -- ) 49 { 50 char s[2]; 51 scanf("%s", s); 52 if (*s == 'C') 53 { 54 int l, r, k; 55 scanf("%d%d%d", &l, &r, &k); 56 add(tr1, l, k), add(tr1, r + 1, -k); 57 add(tr2, l, k * l), add(tr2, r + 1, (r + 1) * (-k)); 58 } 59 else 60 { 61 int l, r; 62 scanf("%d%d", &l, &r); 63 printf("%lld\n", per_sum(r) - per_sum(l - 1)); 64 } 65 } 66 67 return 0; 68 }
第一個操作需要我們將區間中的每個數全部加上x那麼我們樹狀陣列儲存的則是差分陣列,而第二個操作需要我們求出字首和,那麼我們則要對題目條件進行處理。
黑色部分使我們需要查詢操作需要求出來的部分,紅色部分是後來補上。
則這樣我們的黑色部分則為整個矩陣的和減去紅色部分的和,即(a[1] + a[2] + a[3] + ...... + a[n]) * (n + 1) - (a[1] + 2a[2] + 3a[3] + ...... + na[n])。
而這個a陣列使我們儲存在樹狀陣列中的值,則我們的公式變為了sum(n) * (n + 1) - sumi(n)。
所以我們需要儲存兩個樹狀陣列,一個儲存ai,一個儲存i * ai。