数据结构-树状数组
树状数组是较堆功能更强大的 RMQ 数据结构。
数组数组的前置知识:位运算。
数组数组的功能:单点修改区间查询,区间修改单点查询(用差分)。
首先讲 ,这是个位运算知识。表示 二进制下为 的最高位,如 ,, 中的 正好能达到求 的效果。
然后树状数组中的 数组是个有跳跃性的前缀和数组,它通过 跳跃维护,然后通过 跳跃取值。原理较为复杂,不必深究。但是它有如下性质:
1.每次在 位置上 时,可以这样维护 :
void fix(Tree&t,int n,int x,int y){
for(;x<=n;x+=low(x)) t.c[x]+=y;
}
2.如下方法即可求出 :
int fsum(Tree&t,int x){
int res=0;
for(;x;x-=low(x)) res+=t.c[x];
return res;
}
所以树状数组的空间复杂度为 ,时间复杂度为 。
主要操作大概就是这样,那么蒟蒻就放代码了:
namespace Sumtree{
int low(int x){return x&(-x);}
class Tree{
public:
int c[N];
Tree(){memset(c,0,sizeof(c));}
}st;
void fix(Tree&t,int n,int x,int y){// 在x位置上+y
for(;x<=n;x+=low(x)) t.c[x]+=y;
}
int fsum(Tree&t,int x){//求出x的前缀和
int res=0;
for(;x;x-=low(x)) res+=t.c[x];
return res;
}
}using namespace Sumtree;
有了前缀数组后,就可以单点修改区间查询了。如果想区间修改单点查询,就把每个 然后每次修改修改区间两端的值,单点查询的时候求和。
比起线段树,树状数组功能较弱,但代码短个几十行。而且后面学树套树的时候,数组数组会好套很多。
祝大家学习愉快!
来源:CSDN
作者:KonnyWen
链接:https://blog.csdn.net/KonnyWen/article/details/104221509