您的位置:首页 > 其它

树状数组模板

2017-07-13 18:24 405 查看


从图中可以看到,树状数组中用的C[ ],每个点都有一定的管辖范围;

如C[1]=a[1];

C[2]=a[1]+a[2];

C[3]=a[3];

C[4]=a[1]+a[2]+a[3]+a[4];等等;

基础模板:

int lowbit(int x)
{
return x&(-x);
}


这个函数主要是用来求的是某个点管辖范围;

如果是x+=x&(-x);就是得到的改点的父节点的值;比如x=4时;就能得到8;

而x-=x&(-x)的话,就是得到x这个点的管辖区间的下个区间的管辖点;

比如说,x=7,代入后6;不断循环到0能依次得到 6.。。4.;

把他们所有的管辖区间正好是1….7;

void add(int x, int num)
{
while(x<=N)
{
c[x]+=num;
x+=lowbit(x);
}
}


这个函数,是用来修改树状数组的;

如果是一般的算法只用修改改点就可;但是树状数组必须修改所有改点被管辖的区间;

int getsum(int x)
{
int s=0;
while(x>0)
{
s+=c[x];
x-=lowbit(x);
}
return s;
}


这个函数就是求区间和了。。比如getSum(7)的话,就是求a[1]+a[2]+…a[7];

进阶用法:

(1)区间更细+单点查询

思路:和一维数组求前缀和一样,右区间-左区间差值就是区间更新的值

int c
;//树状数组//这里c[x]表示该店元素与左边元素的差值
int lowbit(int x) { return x&(-x); }
void add(int x, int num) { while(x<=N) { c[x]+=num; x+=lowbit(x); } }
void update(int x,int y,int num)
{
add(x,num);
add(y+1,-num);
}
int getsum(int x) { int s=0; while(x>0) { s+=c[x]; x-=lowbit(x); } return s; }


(2)区间更新+区间查询

思路:sum(sum(C[j],j<=i)i<=x)

= x*C[1]+(x-1)*C[2]+……+C[x]

=(x+1)*sum(C[i],i<=x)-sum(i*C[i],i<=x);

这里用两个树状数组来维护区间更新的值

原始数组保存前缀和,则所求区间[x,y]的值为:ans[y]-ans[x-1]+query(x,y)

int c[2][N];//c[0][x]维护c[x]的值,c[1][x]维护c[x]*x的值
int ans
;//原始数据数组的前缀和
int lowbit(int x) { return x&(-x); }
void add(int i,int x, int num)
{
while(x<=N)
{
c[i][x]+=num;
x+=lowbit(x);
}
}
void update(int x,int y,int num)
{
add(0,x,num);//更新c[0][x]的值(x[x])
add(0,y+1,-num);
add(1,x,x*num);//更新c[1][x]的值(c[x]*x)
add(1,y+1,-(y+1)*num);
}
int sum(int i,int x)
{
ll s=0;
while(x>0)
{
s+=c[i][x];
x-=lowbit(x);
}
return s;
}
int getsum(int x)
{
return (x+1)*sum(0,x)-sum(1,x);
}
int query(int x,int y)
{
return getsum(y)-getsum(x-1);
}


树状数组求区间最大值:

void Init()
{
memset(a,0,sizeof(a));
memset(h,0,sizeof(h));
}
int lowbit(int x)
{
return x & (-x);
}
void updata(int x)  //更新操作为:a[i]=输入值,updata(i);(i从1开始)
{
int lx, i;
while (x <= n)
{
h[x] = a[x];
lx = lowbit(x);
for (i=1; i<lx; i<<=1)
h[x] = max(h[x], h[x-i]);
x += lowbit(x);
}
}
int query(int x, int y)  //区间[x,y]
{
int ans = 0;
while (y >= x)
{
ans = max(a[y], ans);
y --;
for (; y-lowbit(y) >= x; y -= lowbit(y))
ans = max(h[y], ans);
}
return ans;
}


下面还有一些树状数组的高级应用(由Lawrence_Jang大牛总结):

http://blog.csdn.net/lawrence_jang/article/details/8054173
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: