4.2 树状数组

树状数组

前言:树状数组可以解决的,线段树也可以解决,树状数组只是在一些问题上有奇效,优先建议练习时还是优先使用线段树

**本质上,解决的问题实际是 差分数组 − > 原始数组 − > 前缀和数组 差分数组->原始数组->前缀和数组 差分数组>原始数组>前缀和数组这其中要使用其二或其三的一种使用树优化效率的一种方法

1. 单点修改+区间查询

const int N = 1000;
#define lowbit(x)  ((x) & - (x))
int tree[N]={0};

void update(int x, int d) {   //单点修改:修改元素a[x],  a[x] = a[x] + d
     while(x <= N) {
        tree[x] += d;
        x += lowbit(x);
     }
}

int sum(int x) {             //查询前缀和:返回前缀和sum = a[1] + a[2] +... + a[x]
    int ans = 0;
    while(x > 0){
        ans += tree[x];
        x -= lowbit(x);
    }
    return ans;
}

2. 区间修改+单点查询

在上面的基础上,每个节点由差分数组组成

对于区间,左端L节点 + d +d +d,右端R+1节点 − d -d d

用sum求得单点值

3. 区间修改+区间查询

在上面的基础上,每个节点由差分数组组成

s u m ( L , R ) = s u m ( 1 , R ) − s u m ( 1 , L − 1 ) sum(L,R)=sum(1,R)-sum(1,L-1) sum(L,R)=sum(1,R)sum(1,L1)

s u m ( 1 , R ) = ∑ i = 1 k D i − ∑ i = 1 k ( i − 1 ) D i sum(1,R)=\sum_{i=1}^{k}{D_i}-\sum_{i=1}^k{(i-1)D_i} sum(1,R)=i=1kDii=1k(i1)Di

从而实现从差分数组到前缀和的转变

4. 单点修改+区间最值

const int N = 2e5+10; 
int n,m,a[N],tree[N]; 
int lowbit(int x){return x&(-x);}

void update(int x,int value){          //更新tree[x]的最大值
    while(x<=n){
        tree[x]=value;
        for(int i=1;i<lowbit(x);i<<=1)
            tree[x]=max(tree[x],tree[x-i]);
        x+=lowbit(x);
    }
}

int query(int L,int R){               //关于区间[L,R]的最值
    int ans=;
    while(L<R){
        ans=max(ans,a[R]);
        R--;
        while(R-L>=lowbit(R)){
            ans=max(ans,tree[R]);
            R-=lowbit(R);
        }
    }
    return ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值