我会树状数组啦哈哈哈

  树状数组资瓷的基本操作有两个,第一个是查询前缀和,第二个是单点增加。利用差分的思想可以达到区间增加和单点查询的操作,复杂度全是log元素数量,十分优秀。

  (说起来用c[i]-c[i-1]也可以在2*logn的时间单点查询,我甚至还能存一下本来的数组,就是O(1)了啊)

  这里的c数组就是树状数组的表示方式了。这个玩意儿真的是靠lowbit()一手撑起来的数据结构了……

  lowbit(i)表示i二进制分解后第一个出现1的位置,也是c[i]在原数组中表示的元素和的长度。

  lowbit()的代码如下。什么?你问我证明?它就是那样的嘛,我的老师又没讲,怪我喽。

1 int lowbit(int x)//这里的x一定要是非负整数int
2     return x&(-x);

  怎么利用呢,就是c[i]=∑o[f],(i-lowbit(i)<f<=i);为什么呢?因为建立的时候就是按这个规则建立的,我这样说你懂了吧?

  这个时候应该放一个图了……

  

  其实只要看这个图自己手推一会就能明白很多了,推荐大家输出一下1-9的lowbit(),一点就通。

  假设我们已经建好了,那输出sum[n]就可以把c[n]利用lowbit()向前推,一直推进零里,经过的节点一定完全覆盖了1-n的原数组了

1 for(i=n,ans=0;i!=0;i-=lowbit(i))
2     ans+=c[i];

  证明嘛,自己看图好了。

  那么如何建立呢?根据图可以得出c[i]的父节点是c[i+lowbit(i)],那么c[i]加一个值它的父节点们也加一波就完事了。

  它的空间复杂度是n,也就是说加到c[n]以后一定停下来,那么就有代码

for(f=i;f<=n;f+=lowbit(f))//n为原数组元素数量
    c[f]+=o[i];

  修改的话是差不多的。比如把o[x]加t就是这样弄

o[x]+=t;
for(;x<=n;x+=lowbif(x))
    c[x]+=t;

t当然也能是负数啦。

猜你喜欢

转载自www.cnblogs.com/qywyt/p/9326065.html