什么是树状数组?顾名思义,就是一个数组,但是却可以看成是一棵树,它以树的方式来存储数据。
测试程序:
如果我们给定一个数组,要求里面全部数据的和,一般来说会想到累加,但其时间复杂度是o(n),有的情况下,当询问多次时不能满足我们的需求。也有的人说用前缀和不就好了,但如果遇上要某个数加上一个数据呢?这样显然是不行的,我们就要用到树状数组了。
那我们一定要用这张图了:
那么观察存储方式,我们很难发现什么,但如果将其转化成二进制就简单多了!如:6=110,它最低一位是2,证明在a[6]中存储的是第5、6个数据之和,即从n开始往前lowbit(n)个数据和(包括第n个)。
lowbit可以这样写:
n=n&(-n);
原理是什么?我不想说......
-n即是n的按位取反再加一,这个不用说吧......
知道了如何存储,我们就可以针对这个写出【某个位置的数加上一个数】和【求1~x的和】这两种关于树状数组的函数。代码如下:
【某个位置加上一个数】
void change(int x,int add)
{
while(x<=n)
{
a[x]+=add;
x+=(x&(-x));
}
}
【求1~x的和】
int sum(int x)
{
int s=0;
while(x>0)
{
s+=a[x];
x-=(x&(-x));
}
return s;
}
#include<iostream>
using namespace std;
int a[100],k,n;
int sum(int x)
{
int s=0;
while(x>0)
{
s+=a[x];
x-=(x&(-x));
}
return s;
}
void change(int x,int add)
{
while(x<=n)
{
a[x]+=add;
x+=(x&(-x));
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;++i)
{
cin>>k;
change(i,k);
}
for(int i=1;i<=n;++i)
cout<<a[i]<<" ";
cout<<endl<<sum(n)<<endl;
}
以上就是关于树状数组的一些初步介绍。
虽然学了一种新的数据结构,但很可惜我们还没有遇到练手的题目,所以也不知道成果如何啊......