算法学习笔记【树状数组】

树状数组是一种高效的数据结构,支持单点修改和区间查询操作,时间复杂度为O(logn)。它基于二进制构造,利用lowbit函数找到最小位的1,实现快速更新和查询。文章通过代码示例解释了如何实现树状数组以及如何进行操作。

目录

什么是树状数组

树状数组的作用

单点修改

 区间查询

代码实现树状数组


制作不易,点个赞再走呗

什么是树状数组

树状数组(Binary Index Tree, BIT)是很多竞赛队员心中最简洁优美的数据结构之一。最简单的树状数组支持两种操作,时间复杂度均为 O(logn) :

单点修改: 更新指定点的数据

区间查询: 查询指定区间内的数据的和

当然,树状数组的作用远不止这些,这里只讨论基本的数据结构。但是树状数组的操作比较局限,虽然代码比线段树少,但却没有线段树进行的操作多,我也写过一个线段树的博客,有兴趣的可以了解一下

线段树学习笔记

结合模板题更好理解该算法:

洛谷:P3374 【模板】树状数组 1

树状数组的作用

先了解树状数组是怎样的

想必大家也不愿意看那些一大串的文字,那么我就用图来讲解。

这样写描述是不是更加直白一些了。

了解到了图形的结构,那么我们就来探讨一下怎么构造这个结构。

因为我们是通过二进制来进行构造结构的,又通过图形,我们知道了我们想求哪一层就需要找到那个最小位的那个1是在哪个位置,这是我们需要应用一个函数 (lowbit 函数)通过这个函数我们可以求得最小位那个1是在哪个位置

代码实现:

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

浅谈一下为什么 x&-x 可以实现找到最后一位:

-x在二进制中可以表示补码,而补码就是原码取反再加一

 那么取 x&-x 就可以求得最小位置的那个1。

单点修改

有同学可能会问了,为什么没有建树这以环节,那当然是因为,这个树不用建,只需要一一对应修改就好了,这就是为什么叫树状数组,而不叫树。

int tree[N];
int lowbit(int x)
{
	return x&-x;
}
void add(int x,int k)
{
	for(int i = x; i <= n; i+=lowbit(i)) tree[i] += k;
}

 区间查询

int lowbit(int x)
{
	return x&-x;
}
int sum(int x)
{
	int res = 0;
	for(int i = x; i ; i -= lowbit(i)) res += tree[i];
	return res;
}

  这个就好理解了,就是将tree前面对应的阶段对应的所有值加在一起,返回一个求1-x 的值。

那么我们就可以用 s[1,r] - s[1,l-1] 求得 s[l , r] 的和。

代码实现树状数组

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 500005;
int arr[N];
int tree[N];
int n,m;

int lowbit(int x)
{
	return x&-x;
}
void add(int x,int k)
{
	for(int i = x; i <= n; i+=lowbit(i)) tree[i] += k;
}
int sum(int x)
{
	int res = 0;
	for(int i = x; i ; i -= lowbit(i)) res += tree[i];
	return res;
}
int main ()
{
	cin >> n >> m;
	for(int i = 1; i <= n; i++)
	{
		scanf("%d",&arr[i]);
		add(i,arr[i]);
	}
	for(int i = 1; i <= m; i++)
	{
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		if(a == 1)
		{
			add(b,c);
		}
		else {
			printf("%d\n",sum(c)-sum(b-1));
		}
	}
	
	return 0;
}

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值