树状数组

当使用前缀和或者差分数组的时候,一般会遇到O(n2)的时间复杂度,此时我们可以使用树状数组来对时间复杂度进行优化。

树状数组主要是利用树形结构来优化我们前缀和或差分数组的计算复杂度使得O(n)的时间复杂度变为O(logn),使用总的时间复杂度减少到O(nlogn).。

构建树状数组的核心是lowbit:

lowbit(x)即x&(-x),效果为得到x最后一个1的位置。比如3&-3等于1表示3的最后一个1在第1位。

-3表示3的补码也就是取反加一。

总的代码如下:

复制代码
#include <iostream>
using namespace std;
const int N = 1000;
#define lowbit(x) ((x)&-(x))
int tree[N] = { 0 };
void Update(int x, int d) {
    while (x <= N) {
        tree[x] += d;
        x += lowbit(x);
    }
}
int sum(int x) {
    int ans = 0;
    while (x > 0) {
        ans += tree[x];
        x -= lowbit(x);
    }
    return ans;
}
void Print_arr(int* arr,int size) {
    for (int i = 0; i < size; i++) {
        cout << *(arr + i) << " ";
    }
    cout << endl;
}
void Print_sum_arr(int size) {
    for (int i = 0; i <= size; i++) {
        cout << sum(i) << " ";
    }
}
int a[11] = { 0,4,5,6,7,8,9,10,11,12,13 };
int main()
{

    for (int i = 1; i <= 10; i++) Update(i, a[i]);
    //Print_arr(tree, 11);
    Print_sum_arr(11);
    cout << sum(8) - sum(4) << endl;
    return 0;
}
复制代码

 

 (来自<<算法竞赛>>)

对于Update函数的说明:

void Update(int x, int d) {//更新所有在树状数组中与x有关的数据,使用lowbit查找
    while (x <= N) {
        tree[x] += d;
        x += lowbit(x);
    }
}

举例说明:对第一个元素更新的时候,1的lowbit为1,那么下一个更新的元素为2,2的lowbit为2,下一个更新4,4的lowbit为8更新8以此类推。

Update之和的,tree里面保存的元素对应上图中的a

 

对于sum函数的说明:

int sum(int x) {//求前缀和
    int ans = 0;
    while (x > 0) {
        ans += tree[x];
        x -= lowbit(x);//由于之前是按照+lowbit(x)进行更新的,现在-lowbit(x)得到的位置就是该位置前缀和需要用到的元素。
    }
    return ans;
}

举例说明:对于第8个元素,8的lowbit为8,但由于之前更新1,2,3,4,5,6,7的时候会对8更新,所以tree[8]就是前八个元素之和

举例说明2:对于第7个元素,7的lowbit为1,更新后6的lowbit为2,4的lowbit为3,结束更新。因此前七个元素之和计算公式为tree[7]+tree[6]+tree[4]。

    依次分析:tree[4]表示的是:1,2,3更新过以及4本身,因此tree[4]就是前四个元素之和。

          tree[6]表示的是5更新加上6本身,因此tree[6]是第5、6个之和

举例说明3:对于第6个元素,6的lowbit为2,那么-lowbit之和变为4,在进行-lowbit为0.因此前6个元素之和为tree[6]+tree[4]

    cout << "tree[4]:" << tree[4] << endl;
    cout << "tree[6]:" << tree[6] << endl;
    cout << "sum(6):" << sum(6) << endl;

 

 可以看到sum(6)为tree[4]和tree[6]之和

           

posted @   海蓝笨  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示