您的位置:首页 > 其它

树状数组

2015-03-14 09:23 134 查看


基本概念

设A[1..N]为一个长为N的序列,即对于序列A有以下操作:

【1】修改操作:将A[x]的值加上c;

【2】求和操作:求此时A[l..r]的和。

} 原数组a

} 树状数组C

C1=a1

C2=a1+a2

C3=a3

C4=a1+a2+a3+a4

C5=a5

C6=a5+a6

C7=a7

C8=a1+a2+a3+a4+a5+a6+a7+a8

……


C[X]的含义

C[x]管辖的区间为2^k个元素,其中k为x二进制末尾0的个数

C[x] = a[x– 2^k + 1] + … + a[x]

K的计算

求k的函数代码如下:

int Lowbit(int t)

{

return t & ( -t );

}


快速求和(复杂度logN)

Sum[9] = C[9]+C[8]

Sum[8] = C[8]

Sum[7] = C[7]+C[6]+C[4]

…..

求a[1]—a[end]和的函数代码如下:

int Sum(int end)

{

int sum = 0;

while(end > 0)

{

sum += C[end];

end -= Lowbit(end);

}

return sum;

}


修改数组a的某个元素值(复杂度logN)

例如 a[3]+x

影响C[3], C[4], C[8]…

void Update(int pos , int num)

{

while(pos <= n)

{

C[pos] += num;

pos += Lowbit(pos);

}

}


线段树与树状数组比较

} 树状数组和线段树一样,是一种很高效的数据结构。但是在于空间耗费较小。

} 对于长度为n的线段(区间),线段树需要2n的空间,而树状数组只要n即可。

} 树状数组的另一个优点是编程简单。

} 树状数组的致命缺点是无法记录一些附加信息。

} 比如“区间总长度” 就无法用树状数组维护。

} 树状数组的应用范围是很窄的

} 求和的问题可以用树状数组;

} 如果求最大值操作、而且没有删除操作的话,那也能够用树状数组
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: