树状数组概念
树状数组的目的
树状数组是用了求动态前缀和的数据结构
时间复杂度修改和查询的时间代价都是O(logn),其中 n为需要维护前缀和的序列的长度。
如何理解呢?比如我们拿[5,5,2,3,6]来举例,我们需要求满足1<=i<j<=len且num[i]<num[j]的(i,j)个数
此时我们已数组的值为创建Tree的依据
index -> 1 2 3 4 5 6 7 8 9
value -> 0 1 1 0 2 1 0 0 0
我们至于要对Tree进行操作就能得到相应的结构且Tree的大小从1开始
- 第一种Tree,以值作为Tree数组的长度
- 第二种,离散化,以长度作为Tree的长度
lowbit函数其实是一个将数组划分的依据,如上图所示,设我们1-3区间的前缀,既求querty(3)
3-lowbit(3)=2;此时querty(3)=tree[3]+tree[2]
树状数组模板
数组从1开始
int lowbit(x){
return x&(-x);
}
int querty(int x){//查询区间1-x的前缀和
int res=0;
while(x){
res+=tree[x];
x-=lowbit(x);
}
return res;
}
void update(int x){//更新x的前缀,并更新受x影响的前缀
while(x){
tree[x]++;
x+=lowbit(x);
}
}