关于树状数组
Posted intmian
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于树状数组相关的知识,希望对你有一定的参考价值。
lowbit是什么?
- lowbit(i)=i&-i
- 对应于末尾的1所在位置的一个数
- 节点高度/对应区间长度
i的父节点为lowbit(i)+i
- 可以观察到它的兄弟节点即是它的父节点
- 最少加上lowbit(i)后lowbit才会增加,即lowbit(i)+i为离i最近的上一层节点
点修改
区间和
void add(int no,int num){
for(int i=no;i<=n;i+=i&-i)
c[i]+=num;
}
区间最值
- 更新所有父节点
- 在每个节点中,采用倍增的思想:
max[12]=max(a[12],c[12-1],c[12-2]) | ||||
c[12] | a[12] | c[12-1] | c[12-2] | lowbit | 4 | 1(元素本身) | 1 | 2 |
void update(int no,int num){
c[no]=a[no]=num;
for(int i=1;i<(no&-no);i<<=1)
c[no]=max(c[no],c[no-i]);
}
区间询问
区间和(前缀和)
倍增:sum[5]=c[4]+c[5];
int ask(int no){
int out=0;
for(int i=no;i;i-=i&-i)
out+=c[i];
return out;
}
区间最值
3=(11)2
11=(1011)2
max(3,11)=max(a[11],c[10],a[8],c[7],c[5],a[4],c[3]) | |||||||
a[11] | a[10] | a[8] | a[7] | a[5] | a[4] | a[3] | |
lowbit | 1 | 2 | / | 1 | 2 | / | 1 |
之后 | 1010 | 1000 | 111 | 110 | 100 | 11 | |
之前 | 1011 | 1010 | 1000 | 111 | 110 | 100 | 11 |
int ask(int l,int r){
int ans=0;
while(r>=l)
{
ans=max(ans,a[r]);
r--;
for(;r-(r&-r)>=l;r-=r&-r)
ans=max(ans,h[r]);
}
return ans;
}
以上是关于关于树状数组的主要内容,如果未能解决你的问题,请参考以下文章