zoukankan      html  css  js  c++  java
  • 树状数组

      树状数组(Binary Indexed Tree(BIT), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值.

      理论上用BIT(树状数组)能解决的问题  ,线段树都可以解决 , 但是明显前者的代码量少.

      让我们大概看看怎么样的:

      据图可知:c1=a1,c2=a1+a2,c3=a3,c4=a1+a2+a3+a4,c5=a5,c6=a5+a6,c7=a7,c8=a1+a2+a3+a4+a5+a6+a7+a8,c9=a9...

      还是看代码吧

      

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    const int MAXN = 1e5 + 5;
    int bit[MAXN] , n;
    
    void init() {
        memset(bit , 0 , sizeof(bit));
    }
    
    int lowbit(int i) {
        return i&-i; //i的二进制最低非0对应的幂  1->1    3->1   2->2   8->8;
    }
    
    int sum(int i) {    //sum(5) = bit[4] + bit[5];  
        int s = 0;
        while(i > 0) {
            s += bit[i];
            i -= lowbit(i);  //去掉二进制最后一个1以及之后的0
        }
        return s;
    }
    
    void add(int i , int x) {      // 比如 bit[5]  =>  bit[6]  =>  bit[8]
        while(i <= n) {
            bit[i] += x;         //区间更新
            i += lowbit(i);      //找到关联的区间
        }
    }
    
    int main() {
        init();
        cin >> n;
        //初始化赋值
        for(int i = 1 ; i <= n ; i++) { 
            cin >> num;
            add(i , num);
        }
        int q_l , q_r;
        cin >> q_l >> q_r;
        cout << sum(q_r) - sum(q_l) << endl;
    }

    下面来做个题目

    链接:http://codeforces.com/gym/100741/problem/A

    注意s操作的时候,当a[i]%m == mod时且在区间l~r内,计算他的和。

    下面是我的代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    const int MAXN = 1e4 + 5;
    __int64 bit[11][MAXN] , equ , a[MAXN];
    int n;
    
    int lowbit(int i) {
        return i & -i;
    }
    
    __int64 Sum(int i , int k) {
        __int64 sum = 0;
        while(i > 0) {
            sum += bit[k][i];
            i -= lowbit(i);
        }
        return sum;
    }
    
    void Add(int i , int add , int k) {
        while(i <= n) {
            bit[k][i] +=  add;
            i += lowbit(i);
        }
    }
    
    int main() {
        int m;
        while(~scanf("%d %d" , &n , &m)) {
            memset(bit , 0 , sizeof(bit));
           for(int i = 1 ; i <= n ; i++) {
                scanf("%I64d" , a + i);
                Add(i , a[i] , a[i] % m);
            }
            int q , l , r;
            char c;
            scanf("%d" , &q);
            while(q--) {
                getchar(); 
                c = getchar();
                if(c == 's') {
                    scanf("%d %d %I64d" , &l , &r , &equ);
                    cout << Sum(r , equ) - Sum(l - 1 , equ) << endl;
                }
                else if(c == '+') {
                    scanf("%d %I64d" , &l , &equ);
                    Add(l , -a[l] , a[l] % m);
                    a[l] += equ;
                    Add(l , a[l] , a[l] % m);
                    cout << a[l] << endl;
                }
                else {
                    scanf("%d %I64d" , &l , &equ);
                    if(a[l] - equ > 0) {
                        Add(l , -a[l] , a[l] % m);
                        a[l] -= equ;
                        Add(l , a[l] , a[l] % m);
    
                        cout << a[l] << endl;
                    }
                    else{
                        cout << a[l] << endl;
                    }
                }
            }
        }
    }
  • 相关阅读:
    MySQL mysqlbinlog 读取mysql-bin文件出错
    MySQL slow_log表不能修改成innodb引擎
    Linux 进程一直占用单核CPU分析
    Linux 磁盘告警分析
    Linux 查看文件被那个进程写数据
    springboot项目访问jsp404
    springboot项目启动控制台显示端口被占用解决方法
    js密码强弱正则校验、邮箱校验
    Java Base64加密解密例子
    mysql按日期做曲线图统计,如果当天没有数据则日期不全、补全日期
  • 原文地址:https://www.cnblogs.com/Recoder/p/4847431.html
Copyright © 2011-2022 走看看