C++ 树状数组

1.作用:

 快速单点修改和前缀和查询,复杂度为O(logn)

2.特点:

每个树节点的节点值是所管理的子节点值之和,lowbit()通过取最后一个二进制位,配合与原索引的加 / 减操作进行爬树 / 下树,爬树过程中更新元素增量,下树过程中累计前缀和,由于是树结构,所以更新和获取操作的时间复杂度为O(logn)

3.示意图:

4.C++代码:

#include<iostream>
#include<vector>
using namespace std;

/*
	树状数组:每个节点的节点值是所管理的子节点值之和
	lowbit()通过取最后一个二进制位,配合加减操作进行爬树和下树,爬树过程中更新元素,下树过程中累计前缀和
	由于是树结构,所以更新和获取操作的时间复杂度为O(logn)
*/

class BIT {
private:
	int lowbit(const int& x) { // 树状数组的基本操作,可以理解为爬树和下树的过程
		return x & (-x);
	}
	vector<int>tree; //树状数组
	int sizeT; // 数组大小
public:
	// 因为lowbit(0)还是0,没有意义,因此tree[0]是不用的
	// tree[0]是不用的,从tree[1]开始,因此tree(size+1)
	explicit BIT(int size):sizeT(size), tree(size+1) {} // explicit防止类构造函数的隐式自动转换

	void update(int idx, int val) { // 元素更新,val为元素的增量,如果原数组值为0,则直接输入更新的元素值
		while (idx <= sizeT) {
			tree[idx] += val; // 爬树的过程中更新增量
			idx += lowbit(idx); // 爬树
		}
	}

	int query(int idx) { // 获得前缀和
		int prefix = 0;
		while (idx > 0) { // tree[0]是不用的!
			prefix += tree[idx]; // 下树的过程中累计前缀和
			idx -= lowbit(idx); // 下树
		}
		return prefix;
	}

	void print(vector<int>& arr) {
		for (const int& num : arr) cout << num << ' ';
		cout << endl;
	}
};

int main() {
	vector<int>arr(10);
	BIT bit(10);
	for (int i = 0; i < 10; ++i) {
		arr[i] = rand() % 20;
		bit.update(i+1, arr[i]);
	}
	bit.print(arr);
	for (int i = 0; i < 10; ++i) {
		cout << bit.query(i+1) << ' ';
	}
	cout << endl;
	return 0;
}

 做笔记使用,树状数组的理解方面还不是特别透彻,如果有大神看到了还希望多多指点!!!

谢谢!!溜了溜了~~~

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦想是优秀社畜

您的打赏是对我最大的鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值