树状数组代码学习

这里直接放上写的学习代码,都是模板,目的是理解这个工具是干什么的(理解什么的在这里):

学习思路参考的这里

 1、单点修改, 区间查询

 1 /*
 2 单点修改, 区间查询
 3 5 5
 4 1 5 4 2 3
 5 1 1 3
 6 2 2 5
 7 1 3 -1
 8 1 4 2
 9 2 1 4
10 answer:14
11        16 
12 */
13 #include <bits/stdc++.h>
14 using namespace std;
15 
16 const int N = 500005, M = 500000;
17 #define lowbit(x) (x&(-x))
18 int c[N], n, m;
19 int sum(int x){
20     int ret = 0;
21     while(x > 0){
22         ret += c[x];
23         x -= lowbit(x);
24     }
25     return ret;
26 }
27 void add(int x, int d){
28     while(x <= n){
29         c[x] += d;
30         x += lowbit(x);
31     }
32 }
33 int main(){
34 //    freopen("in.txt", "r", stdin);
35     scanf("%d%d", &n, &m);
36     for(int i=1; i<=n; i++){
37         int d;
38         scanf("%d", &d);
39         add(i, d);
40     }
41     for(int i=0; i<m; i++){
42         int op, x, y;
43         scanf("%d%d%d", &op, &x, &y);
44         if(op==1){
45             add(x, y);
46         }else{
47             printf("%d
", sum(y)-sum(x-1));
48         }
49     }
50     return 0;
51 }
View Code

2、区间修改,单点查询

 1 /*
 2 区间修改, 单点查询
 3 5 5
 4 1 5 4 2 3
 5 1 2 4 2
 6 2 3
 7 1 1 5 -1
 8 1 3 5 7
 9 2 4
10 answer:6 
11        10 
12 */
13 #include <bits/stdc++.h>
14 using namespace std;
15 #define lowbit(x) (x&(-x))
16 const int N = 500005, M = 500000;
17 int c[N], n, m;
18 void add(int x, int d){
19     while(x <= n){
20         c[x] += d;
21         x += lowbit(x);
22     }
23 }
24 int sum(int x){
25     int ret = 0;
26     while(x > 0){
27         ret += c[x];
28         x -= lowbit(x);
29     }
30     return ret;
31 }
32 int main(){
33 //    freopen("in.txt", "r", stdin);
34     scanf("%d%d", &n, &m);
35     int x=0, y;
36     for(int i=1; i<=n; i++){
37         scanf("%d", &y);
38         add(i, y-x);
39         x = y;
40     }
41     for(int i=0; i<m; i++){
42         int op, k;
43         scanf("%d", &op);
44         if(op==1){
45             scanf("%d%d%d", &x, &y, &k);
46             add(x, k);
47             add(y+1, -k);
48         }else{
49             scanf("%d", &x);
50             printf("%d
", sum(x));
51         }
52     }
53     return 0;
54 }
View Code

3、区间修改,区间查询( 这里差分原数组构造数组d,维护两个树状数组d[i]和d[i]*i )

 1 /*
 2 区间修改, 区间查询
 3 3
 4 1
 5 2 
 6 3
 7 2
 8 1 2 3 2
 9 2 2 3
10 answer: 9 
11 */
12 #include <bits/stdc++.h>
13 using namespace std;
14 #define lowbit(x) (x&(-x))
15 const int N = 500005, M = 500000;
16 int c1[N], c2[N], n, m;
17 int sum(int x){
18     int ret = 0;
19     while(x > 0){
20         ret += (x+1)*c1[x]-c2[x];
21         x -= lowbit(x);
22     }
23     return ret;
24 } 
25 void add(int x, int d){
26     while(x <= n){
27         c1[x] += d; c2[x] += x*d;
28         x += lowbit(x);
29     }
30 }
31 int main(){
32     freopen("in.txt", "r", stdin);
33     scanf("%d", &n);
34     int x=0, y;
35     for(int i=1; i<=n; i++){
36         scanf("%d", &y);
37         add(i, y-x);
38         x = y; 
39     }
40     scanf("%d", &m);
41     for(int i=0; i<m; i++){
42         int op, k;
43         scanf("%d", &op);
44         if(op==1){
45             scanf("%d%d%d", &x, &y, &k);
46             add(x, k);
47             add(y+1, -k); 
48         }else if(op==2){
49             scanf("%d%d", &x, &y);
50             printf("%d
", sum(y)-sum(x-1));
51         }
52     }
53     return 0;
54 }
View Code

LA 4329 - Ping pong

题意:n个人,三人一对比赛,中间为裁判,技能值也在两人中间(大中小, 小中大两种),问一共能组织多少中比赛。

树状数组的题目需要构造前缀和(当然不一定只是和),这里假设ai到ai-1有ci个比ai小,则有i-1-ci个比ai大,假设ai+1到an中有di个比ai小,则有n-i-di个比ai大。乘法原理和加法原理得ci*(n-i-di)+di*(i-ci-1)种比赛。

构造前缀和:x[j]表示目前为止已经考虑过的所有ai中,是否存在一个ai=j(x[j]=0表示不存在,x[j]=1表示存在),则ci=x[1]+……+x[a[i]-1],前缀和出现。

初始x[i]=0,在计算ci时,需要设x[a[i]]=1,更新后缀和,再求前缀和sum(a[i] - 1)。

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <cctype>
 6 #include <string>
 7 #include <cstring>
 8 #include <algorithm>
 9 #include <stack>
10 #include <queue>
11 #include <set>
12 #include <map>
13 #include <ctime>
14 #include <vector>
15 using namespace std;
16 #define LL long long
17 #define lowbit(x) ((x)&(-x))
18 #define mem(s) memset(s, 0, sizeof(s))
19 const int inf = 0x3f3f3f3f;
20 const int maxn = 20010, maxa = 1e6+10;
21 int a[maxn], c[maxa], d[maxn], s[maxn], Max;
22 int sum(int x){
23     int s = 0;
24     for(;x;x-=lowbit(x)) s+=c[x];
25     return s;
26 }
27 void add(int x, int d){
28     for(;x<=Max;x+=lowbit(x)) c[x]+=d;
29 }
30 int main() 
31 {
32     freopen("in.txt", "r", stdin);
33     int T;
34     scanf("%d", &T);
35     while(T--){
36         int n;
37         scanf("%d", &n);
38         Max = 0;
39         for(int i=1; i<=n; i++){
40             scanf("%d", &a[i]);
41             Max = max(Max, a[i]);
42         }
43         mem(c);
44         for(int i=1; i<=n; i++){
45             add(a[i], 1);
46             s[i] = sum(a[i]-1);
47         }
48         mem(c);
49         for(int i=n; i>=1; i--){
50             add(a[i], 1);
51             d[i] = sum(a[i]-1);
52         }
53         LL cnt=0;
54         for(int i=2; i<=n; i++){
55             cnt += (LL)(s[i]*(n-i-d[i])+(i-1-s[i])*d[i]);
56         }
57         printf("%lld
", cnt);
58     }
59     return 0;
60 }
原文地址:https://www.cnblogs.com/seaupnice/p/9465758.html