• 树状数组代码学习


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

    学习思路参考的这里

     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 }
  • 相关阅读:
    MySQL之force index和ignore index
    Linux中CPU性能分析工具perf简单使用(亲测可用)
    Linux之SeLinux
    Docker基础
    yum常用命令
    MySQL总结
    MySQL字符集详解
    MySQL5.6的4个自带库详解
    Python操作MySQL
    MySQL索引原理
  • 原文地址:https://www.cnblogs.com/seaupnice/p/9465758.html
Copyright © 2020-2023  润新知