树状数组

看到树状数组后觉得这个数据结构很优美,比较有意思,虽然很多时候线段树能做,但树状数组内存消耗更小,思想也很有意思,就想记录一下

 

 看上去是比较漂亮的,A[] 是序列的实际数值, C[] 记录的是某一段A[]的和,例如 C[4]就是 sun(1--4)。

先介绍个很关键的函数:int lowbit(int x){return x&(-x);} 这个可以返回二进制数 x 中最低位的 1 还是 1 ,其余都为 0 的数,比如对于 1000(8的二进制) 1000=100+lowbit(100)=110+lowbit(110)=111+lowbit(111);

其实 C[i] 有很多性质:

1,将 i 化为二进制,比如 i = 6 = 110 那么 lowbit(6) = 2 ,代表 C[6] 记录了 2 个数的和, lowbit(7)=1 ,所以 C[7] 记录的 1 个数的和,所以查询时 i-lowbit(i) 会到 C[i] 恰好没覆盖到的地方

2,C[i]的父节点是 C[i+lowbit(i)],也就是说,i+lowbit(i) 是记录了 i 记录的前缀和的,所以更新时要不断向父节点更新。

看懂了这些再看看代码,很容易理解了

 求区间和O(log n),便于单点更新,区间查询:

复制代码
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 
 5 using namespace std;
 6 #define MAXN 1000
 7 
 8 int n;
 9 int A[MAXN];
10 int C[MAXN];
11 
12 int lowbit(int x)
13 {
14     return x&(-x);
15 }
16 
17 void update(int x,int add) //A[x]增减
18 {
19     while (x<=n)
20     {
21         C[x]+=add;
22         x+=lowbit(x);
23     }
24 }
25 
26 void new_tree(int n)   //建树,直接利用update
27 {
28     memset(C,0,sizeof(C));
29     for (int i=1;i<=n;i++)
30         update(i,A[i]);
31 }
32 
33 int getsum(int x)//[1--x]的和
34 {
35     int sum=0;
36     while(x>0)
37     {
38         sum+=C[x];
39         x -= lowbit(x); //性质1
40     }
41     return sum;
42 }
43 
44 int main()
45 {
46     scanf("%d",&n);
47     for (int i=1;i<=n;i++)
48         scanf("%d",&A[i]);
49     new_tree(n);
50 
51     int l,r;
52     scanf("%d %d",&l,&r);
53     printf("%d\n",getsum(r)-getsum(l-1)); //l--r 的和
54 
55     return 0;
56 }
View Code
复制代码

 虽然用前缀和求区间和是O(1),但是不便更新

 

树状数组还可以很方便的做区间更新,单点查询,更新时 update(L,v),update(R+1,-v) ,查询为 get_sum(i), 即可,还是因为树状数组保存的是前缀和的原因

 

 还可以升级到多维的,很厉害

posted @   happy_codes  阅读(138)  评论(0编辑  收藏  举报
编辑推荐:
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
阅读排行:
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 数据库服务器 SQL Server 版本升级公告
· 程序员常用高效实用工具推荐,办公效率提升利器!
· C#/.NET/.NET Core技术前沿周刊 | 第 23 期(2025年1.20-1.26)
点击右上角即可分享
微信分享提示