[模板]-树状数组(一维)

一维树状数组

1.1 单点修改 + 区间和

【任务】修改数组中某个元素,求 [ l , r ] [l,r] [l,r] 区间和。
【说明】原始数组 a [ i ] a[i] a[i], 树状数组 c [ i ] c[i] c[i] 存储 a [ i ] a[i] a[i].
【接口】
           \;\;\;\;\; void update(int i, int x);
           \;\;\;\;\; 复杂度: O ( l o g n ) O(logn) O(logn)
           \;\;\;\;\; 功能:单点修改 a [ i ] + x a[i] + x a[i]+x.
           \;\;\;\;\; 调用:update(i, x).

           \;\;\;\;\; int Query_sum(int i);
           \;\;\;\;\; 复杂度: O ( l o g n ) O(logn) O(logn)
           \;\;\;\;\; 功能:返回前缀和 s u m [ i ] = ∑ k = 1 i a [ k ] sum[i] = \sum_{k=1}^{i} a[k] sum[i]=k=1ia[k].
           \;\;\;\;\; 调用:sum[ l, r ] = Query_sum( r ) - Query_sum( l - 1 ).
【代码】

void update(int i, int x) {  
    for(int k = i; k <= n; k += lowbit(k)) {      // 单点修改 a[i] + x  
        c[k] += x;  
    }     
}  
int Query_sum(int i) {  
    int ans = 0;  
    for(int k = i; k >= 1; k -= lowbit(k)) {      // 前缀和 sum[i]  
        ans += c[k];  
    }  
    return ans;  
}  

1.2 区间修改 + 单点查询

【任务】将区间 [ l , r ] [l,r] [l,r] 中每个数 + x +x +x , 查询数组中某个元素的值。
【说明】原始数组 a [ i ] a[i] a[i], 树状数组 c [ i ] c[i] c[i] 存储 d [ i ] d[i] d[i], d [ i ] = a [ i ] − a [ i − 1 ] d[i] = a[i] - a[i-1] d[i]=a[i]a[i1].
&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; 区间修改可以转化为单点修改:对区间 [ l , r ] [l,r] [l,r] 中每个数 + x +x +x 之后,对于 d [ i ] d[i] d[i] 数组,区间 [ l + 1 , r ] [l+1,r] [l+1,r] 保持不变,只有两个地方需要改 d [ l ] + x , &ThickSpace; d [ r + 1 ] − x d[l] + x, \; d[r+1] - x d[l]+x,d[r+1]x.
&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; 单点查询可以转化为求前缀和: a [ i ] = ( d [ i ] − d [ i − 1 ] ) + ( d [ i − 1 ] − d [ i − 2 ] ) + ⋅ ⋅ ⋅ + ( d [ 2 ] − d [ 1 ] ) a[i] = (d[i] - d[i-1]) + (d[i - 1] - d[i-2]) + \cdot \cdot \cdot + (d[2] - d[1]) a[i]=(d[i]d[i1])+(d[i1]d[i2])++(d[2]d[1]).
【接口】
&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; void update(int k, int x);
&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; 复杂度: O ( l o g n ) O(logn) O(logn)
&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; 功能:单点修改 d [ k ] + x d[k] + x d[k]+x.
&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; 调用:update(l, x), update(r+1, -x).

&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; ll Query_sum(int i);
&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; 复杂度: O ( l o g n ) O(logn) O(logn)
&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; 功能:返回前缀和 s u m [ i ] = ∑ k = 1 i d [ k ] sum[i] = \sum_{k=1}^{i} d[k] sum[i]=k=1id[k].
&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; 调用:a[i] = Query_sum(i).
【代码】

void update(int k, int x) {
	for(int i = k; i <= n; i += lowbit(i)) {
		c[i] += x;
	}
	return;
}
ll Query_sum(int k) {
	ll sum = 0;
	for(int i = k; i >= 1; i -= lowbit(i)) {
		sum += c[i];
	}
	return sum;
}

1.3 区间修改 + 区间和

【任务】将区间 [ l 1 , r 1 ] \left [ l_{1},r_{1} \right ] [l1,r1] 中每个数 + x +x +x , 查询区间和 [ l 2 , r 2 ] \left [ l_{2},r_{2} \right ] [l2,r2]
【说明】原始数组 a [ i ] a[i] a[i], 树状数组 s u m 1 [ i ] sum1[i] sum1[i] 存储 d [ i ] d[i] d[i], d [ i ] = a [ i ] − a [ i − 1 ] d[i] = a[i] - a[i-1] d[i]=a[i]a[i1].
&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; 区间修改:可以转化为单点修改:对区间 [ l , r ] [l,r] [l,r] 中每个数 + x +x +x 之后,对于 d [ i ] d[i] d[i] 数组,区间 [ l + 1 , r ] [l+1,r] [l+1,r] 保持不变,只有两个地方需要改 d [ l ] + x , &ThickSpace; d [ r + 1 ] − x d[l] + x, \; d[r+1] - x d[l]+x,d[r+1]x.
&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; 区间求和: 前缀和 ∑ i = 1 r a [ i ] = a 1 + a 2 + . . . + a r \sum_{i=1}^{r} a[i] = a_{1} + a_{2} + ... + a_{r} i=1ra[i]=a1+a2+...+ar

&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; = d 1 + ( d 1 + d 2 ) + ( d 1 + d 2 + d 3 ) + ⋅ ⋅ ⋅ + ( d 1 + d 2 + . . . + d r ) = d_{1} + (d_{1} + d_{2}) + (d_{1} + d_{2} + d_{3}) + \cdot \cdot \cdot + (d_{1} + d_{2} + ... + d_{r}) =d1+(d1+d2)+(d1+d2+d3)++(d1+d2+...+dr)

&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; = r ⋅ d 1 + ( r − 1 ) ⋅ d 2 + ( r − 2 ) ⋅ d 3 + ⋅ ⋅ ⋅ + 2 ⋅ d r − 1 + d r = r\cdot d_{1} + (r-1)\cdot d_{2} + (r-2) \cdot d_{3} + \cdot \cdot \cdot + 2\cdot d_{r-1} + d_{r} =rd1+(r1)d2+(r2)d3++2dr1+dr

&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; = ∑ k = 1 r ( r + 1 − k ) ⋅ d k = \sum_{k=1}^{r} (r + 1 - k) \cdot d_{k} =k=1r(r+1k)dk

&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; = ∑ k = 1 r ( r + 1 ) ⋅ d k − ∑ k = 1 r k ⋅ d k = \sum_{k=1}^{r} (r + 1) \cdot d_{k} - \sum_{k=1}^{r} k \cdot d_{k} =k=1r(r+1)dkk=1rkdk

&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; 需要第二个树状数组 s u m 2 [ i ] sum2[i] sum2[i] 存储 i ⋅ d [ i ] i \cdot d[i] id[i].

【接口】
&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; void update(int i, int x);
&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; 复杂度: O ( l o g n ) O(logn) O(logn)
&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; 功能:单点修改 d [ i ] + x , d[i] + x, d[i]+x,.
&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; 调用:update(l, x), update(r+1, -x).

&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; ll Query_sum(int i);
&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; 复杂度: O ( l o g n ) O(logn) O(logn)
&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; 功能:返回前缀和 ∑ k = 1 i a [ k ] \sum_{k=1}^{i} a[k] k=1ia[k].
&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace; \;\;\;\;\; 调用:Query_sum( r ) - Query_sum( l - 1 ).
【代码】

void update(int k, ll x) {
	for(int i = k; i <= n; i += lowbit(i)) {
		sum1[i] += x;
		sum2[i] += x * k;
	}
	return;
}

ll Query_sum(int k) {
	ll sum = 0;
	for(int i = k; i >= 1; i -= lowbit(i)) {
		sum += sum1[i] * (k + 1) - sum2[i];
	}
	return sum;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值