加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

树状数组

发布时间:2020-12-14 03:46:57 所属栏目:大数据 来源:网络整理
导读:? 处理何种问题 :常用于动态更新情况下的求区间和,LIS里的求最大值也用到了树状数组。 ? 时间复杂度 :单次更新和求和的时间复杂度都是O(logn) ? 原理 :lowbit()函数是整个树状数组的核心,但是在这里我就不说他的理论基础了,只说一下它的功能,例如:

?

处理何种问题:常用于动态更新情况下的求区间和,LIS里的求最大值也用到了树状数组。

?

时间复杂度:单次更新和求和的时间复杂度都是O(logn)

?

原理:lowbit()函数是整个树状数组的核心,但是在这里我就不说他的理论基础了,只说一下它的功能,例如:给一个原始数组A[]:1,2,3,4,5,6,7,8,9;

被加工之后就是树状数组C[]:1,3,3,10,5,11,7,36,9;即

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

如下图所示:

?

树状数组并不是一个二叉树(不像线段树),对于每一个节点,例如C6,我们需要求的是它的父亲节点和前面一个相邻的兄弟节点是哪一个,这些用lowbit()函数都是可以很快捷的找到,即C6的前一个兄弟节点是6-lowbit(6),而他的父亲节点是6+lowbit(6)。

利用如此操作之后,在动态查询修改之后我们不必对全局进行全部修改,只需要更改节点值就可以了,在log级的时间内完成查询和修改。

lowbit(x)=(x&(-x));

?

实现步骤:具体看代码,略

?

备注:略

?

输入样例解释

10? //数组元素个数

1 2 3 4 5 6 7 8 9 10

2 1 3? // 2代表查询区间[1,3]之和

1 3 6? // 1代表给第3个元素加上6

2 2 7

1 10 -2

1 6 3

2 3 10

?

输出样例解释

6 //查询结果

33

59

//对于树状数组,有利有弊,代码也是的确简单,常用在动态更新求区间和
//当然,某些情况下的求解最大值也是可以做的,代码也的确比线段树好写的多
//单点更新的操作可以利用Sum找出单点值,再用Add更新两次即可

#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;

#define lowbit(x) (x&(-x))
const int MaxN=10001000;
long long arr[MaxN];
int n;

void Build()
{
    memset(arr,sizeof(arr));
    long long temp;
    int j;
    for(int i=1; i<=n; ++i)
    {
        scanf("%lld",&temp);
        j=i;
        while(j<=n)
        {
            arr[j]+=temp;
            j+=lowbit(j);
        }
    }
}
void Add(int x,int val)
{
    while(x<=n)
    {
        arr[x]+=val;
        x+=lowbit(x);
    }
}
long long sum(int x)
{
    long long ans=0;
    while(x>0)
    {
        ans+=arr[x];
        x-=lowbit(x);
    }
    return ans;
}


int main()
{
    int temp,take;
    while(~scanf("%d",&n))
    {
        Build();//建树

        while(scanf("%d",&take))
        {
            if(take==1)//单点添加
            {
                int x,val;
                scanf("%d%d",&x,&val);
                Add(x,val);
            }
            else//求区间和
            {
                int l,r;
                scanf("%d%d",&l,&r);
                printf("%lldn",sum(r)-sum(l-1));
            }
        }

    }
    return 0;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读