码迷,mamicode.com
首页 > 编程语言 > 详细

树状数组

时间:2015-09-29 23:21:09      阅读:259      评论:0      收藏:0      [点我收藏+]

标签:

  树状数组(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;
                }
            }
        }
    }
}

 

树状数组

标签:

原文地址:http://www.cnblogs.com/Recoder/p/4847431.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!