一分钟了解树状数组

一分钟了解树状数组

  1. 树状数组的功能:
    在程序设计中,经常遇到求区间和(query)并且更新区间的某个数值(update)的问题。
    如果不使用任何算法,update的时间复杂度为O(1)但是query的时间复杂度是O(n)
    如果使用前缀和的算法,update的时间复杂度是O(n),query的时间复杂度是O(1)
    也就是说,以上两种算法无论如何都会有一个操作的时间复杂度到达O(n)级别,如果两种操作都要进行多次,消耗时间就会过长。
    如果想要兼顾两种操作的时间复杂度,就需要使用树状数组或者线段树的算法,在这里主要介绍树状数组。
    树状数组的query和update的时间复杂度均为O(logn)

  2. 树状数组的原理
    树状数组的精髓是lowbit()函数,其主要功能是返回某个数二进制最低位上的1的权值。
    例如:
    lowbit(1)=1;
    lowbit(2)=2;
    lowbit(3)=1;
    lowbit(4)=4;
    以下是c代码:

int lowbit(int x){
	return x&-x;
}

或者

#define lowbit(x) -x&x

树状数组中的每个值都等于原数组中前lowbit()项的和。
如下图:
在这里插入图片描述

  1. 树状数组的创建:

//a为原数组,c为树状数组,下同

int a[100100];
int c[100100];
int n;
//a为原数组,c为树状数组,下同
void creat(){
	for( int i=1;i<=n;i++){
		for( int j=0;j<lowbit(i);j++){
			c[i]+=a[i-j];
		}
	}
}

  1. 树状数组的query
    树状数组每个数都是该元素前lowbit()项元素的和(包含该元素本身)
int query( int x){
	int sum=0;
	while(x>0){
		sum+=c[x];
		x-=lowbit(x);
	}
	return sum;
}

求区间和只需要
c[r]-c[l-1]

  1. 树状数组的update
    树状数组的update需要修改树状数组中所有包含下标i的数组元素。
    而从i开始,第一个包含下标i的元素就是i+lowbit(i)
void update( int i,int val){
	while(i<=n){
		c[i]+=val;
		i+=lowbit(i);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值