[笔记] 树状数组

来源:互联网 发布:淘宝c店转企业店铺 编辑:程序博客网 时间:2024/05/22 03:05

维护一个数组序列,支持操作:

1、统计一段区间的数之和O(logn)

2、改变某个位置处的值O(logn)

基本描述:设原数组为a[1..N],树状数组c[1..N],树状数组的下界都是从0开始,这一点需要注意。

c[i]=a[i-(1<<k)+1] + ... + a[i] (k为在二进制表示下末尾0的个数)

程序代码:

计算k

#define Lowbit(x) ((x)&(-x))

计算sum(x),即1到x的和

int sum(int k) {int s=0;while (k!=0) {s=s+c[k];k=k-Lowbit(k);}return s;}


更新c[x]和a[x]

void change(int k, int d) {while (k<=Maxn) {c[k]=c[k]+d;k=k+Lowbit(k);}return;}

扩展到二维状况:需要注意C的下界均为1,不可以出现0

扩展到多维情况的时候需要注意求和时的容斥。

复杂度为O((logn)^k)k为维数。

二维情况:Sum(x2,y2)+Sum(x1-1, y1-1)-Sum(x1-1, y2)-Sum(x2, y1-1)

三维情况:Sum(x2,y2, z2)-Sum(x2, y1-1, z2)-Sum(x1-1, y2, z2)+Sum(x1-1, y1-1,z2)-Sum(x2, y2, z1-1)+Sum(x2, y1-1, z1-1)+Sum(x1-1, y2,z1-1)-Sum(x1-1, y1-1, z1-1)


应用:树状数组在使用的时候,可以用c[]数组记录a[]的最值。这时c[x]表示a[1]到a[x]的最值,这样可以在O(logn)的时间内算出区间的最值。这种用法跟Dp结合的时候可以优化,Dp的复杂度。


题目:

Ural1028 1470

Poj1195 3321 2481 2464 3321

Toj3140 2553 1455


原创粉丝点击