您的位置:首页 > 其它

树状数组

2016-03-08 20:22 190 查看
注:我在修炼当中,博客完全是为了自己复习方便看得,如果你不慎点入了我的博客,看看就好,不要相信,误人子弟就不好了- -

整理一下树状数组的知识,比较可惜的是,以前做题的心得写在word里,后来不小心中病毒了,就没有保存下来,现在还得重新来一遍,不过有新的收获哦。

树状数组查询和修改的时间复杂度都是O(logn)的。主要用于单点修改,区间查询,也可以区间修改,单点查询,我的新收获就在这里。

先看一下它的几个基本函数,一维的情况下,二维在下面的下面。

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


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


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


然后我们来分析一下第一个函数,后面两个就不说了,很好理解。

但是第一个我好像也说不明白,就是很神奇的一件事。

嗯,这几个函数先记住,有时间再说,然后要重点说一下 那个区间更新,单点查询

他其实是这么回事,用一个图来表示

假如我们想使(2,4)区间的数都加上1,那么我们就可以这样做,懂了吧,代码就不用写了



区间更新时用update, 单点查询时用getSum,太神奇了!!!我要回去研究下,明白了再回来更新。

二维的情况就是介个样子

void update(int x, int y, int add )
{
int i, j;
for(i = x;i <= N;i += lowbit(i))
{
for(j = y; j <= N; j += lowbit(j))
{
c[i][j] += add;
}
}
}

int getSum( int x, int y )
{
int sum = 0, i, j;
for(i = x;i > 0;i -= lowbit(i))
{
for(j = y; j > 0; j -= lowbit(j))
{
sum += c[i][j];
}
}
return sum;
}


具体的例题就以后再说吧,话说之前经常看大神的博客,没觉得怎么样,不过自己一写起博客,发现真的没那么容易,尤其是写一篇很好的博客。还得慢慢修炼。

就酱。

继续更新

今天彻底弄懂了树状数组区间修改单点查询和单点更新区间查询的区别,咳咳,让我来讲解一下。

单点更新,区间查询

这个很好理解,单点更新就是用下面这个函数,依次向上更新节点的值

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


区间查询呢就是这个getSum函数

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


依次向前加上节点的值

那么区间更改,单点查询也是用同样的函数,是怎样神奇的完成这个过程的呢

区间更改就是像上面说的,更改(2, 4)之前的值时,使2以后的节点加上增值(注意是在节点也就是c数组),4后面也就是从5开始的节点减去增值,重点就在与这个在节点减去增值。因为4以后的数并没有进行这个增值,所以当用getSum这个本来是用来求和的数组进行查询单点之时,依旧要经过前面的节点,而在这种情况下经过这些关卡,就像是要还之前欠的债一样,你多加的值经过这个关卡之后就减下去了。而有的点比如3,应该增值的点并没有进行增值,那么他走到2的时候就会加回来,这个问题就是这么完美的被解决了。

实在是太神奇了,一直都想说,对哪些研究出那些算法的人表示深深的致敬,你们太了不起了,我理解都要好久- -!

目前对于树状数组的逆序数求法还不太理解,理解了再来更新。

对于树状数组的复习先到这里,各种灵活的用法,要先去自己思考,不能急于求成。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: