单点更新 区间查询 直接利用树状数组存储原数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 #include <bits/stdc++.h> #define LL long long #define Pi acos(-1.0) #define INF 2147483646 #define eps 1e-9 #define MS 100009 #define mss 17 using namespace std;int n,m,k;int p[MS],tr[MS];void input () { for (int i=1 ;i<=n;i++) cin >> p[i]; } int lowbit (int x) { return x&(-x); } void build () { for (int i=1 ;i<=n;i++){ for (int j=i;j<=n;j+=lowbit (j)){ tr[j] += p[i]; } } } void revise_point (int sub ,int val) { p[sub] += val; for (int i=sub;i<=n;i+=lowbit (i)){ tr[i] += val; } } LL get_sum (int i) { LL cnt = 0 ; while (i>0 ){ cnt += tr[i]; i -= lowbit (i); } return cnt; } void output () { for (int i=1 ;i<=n;i++){ cout << p[i] << " " ; } cout << endl; } int main () { cin >> n; input (); build (); cin >> m >> k; revise_point (m,k); output (); cin >> m >> k; cout << get_sum (k) - get_sum (m-1 ) << endl; return 0 ; }
区间更新 单点查询 利用树状数组存储原数组的差分,这样修改区间时只需要修改两个位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 #include <bits/stdc++.h> #define LL long long #define Pi acos(-1.0) #define INF 2147483646 #define eps 1e-9 #define MS 100009 #define mss 17 using namespace std;int n,m,k;int p[MS],tr[MS],a[MS];void input () { for (int i=1 ;i<=n;i++) cin >> p[i]; for (int i=1 ;i<=n;i++) a[i] = p[i] - p[i-1 ]; } int lowbit (int x) { return x&(-x); } void build () { for (int i=1 ;i<=n;i++){ for (int j=i;j<=n;j+=lowbit (j)){ tr[j] += a[i]; } } } void revise_point (int sub ,int val) { a[sub] += val; for (int i=sub;i<=n;i+=lowbit (i)){ tr[i] += val; } } LL get_sum (int i) { LL cnt = 0 ; while (i>0 ){ cnt += tr[i]; i -= lowbit (i); } return cnt; } int main () { cin >> n; input (); build (); int l,r,val; cin >> l >> r >> val; revise_point (l,val); revise_point (r+1 ,-val); cin >> m; cout << get_sum (m) << endl; return 0 ; }
区间更新 区间查询 依旧利用树状数组存储原数组的差分,维护两个数状数组,$sum1[i] = a[i],sum2[i] = a[i]*(i-1)$; 为何维护 .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 #include <bits/stdc++.h> #define LL long long #define Pi acos(-1.0) #define INF 2147483646 #define eps 1e-9 #define MS 100009 #define mss 17 using namespace std;LL n,m,k; LL p[MS],tr[MS],a[MS]; LL sum1[MS],sum2[MS]; int lowbit (int x) { return x&(-x); } void input () { for (int i=1 ;i<=n;i++) cin >> p[i]; } void dif () { for (int i=1 ;i<=n;i++) a[i] = p[i] - p[i-1 ]; } void updata (int sub,LL val) { int x = sub; for (int i=sub;i<=n;i+=lowbit (i)){ tr[i] += val; sum1[i] += val; sum2[i] += val*(x-1 ); } } LL get_sum (int i) { LL cnt = 0 ; int x = i; while (i>0 ){ cnt += x*sum1[i] - sum2[i]; i -= lowbit (i); } return cnt; } int main () { cin >> n; input (); dif (); for (int i=1 ;i<=n;i++){ updata (i,a[i]); } LL l, r, val; cin >> l >> r >> val; updata (l,val); updata (r+1 ,-val); cin >> m >> k; cout << get_sum (k) - get_sum (m-1 ) << endl; return 0 ; }