zoukankan      html  css  js  c++  java
  • 树状数组学习笔记

    先来道题:

    很简单,是吧(有脑子就行)
    伪代码如下:

    时间复杂度:(Theta(n))
    但如果是求(q)(q<10^5))次连续和呢?
    那这样做肯定TLE
    所以我们用前缀和来做:

    比暴力快多了
    但如果频繁修改(a[i])呢?
    那前缀和肯定炸了
    这里,我们引入一种新的算法:树状数组

    这是树状数组
    我们把它更直观的表示下——
    这是原来的树:

    我们把它右对齐:

    这便是树状数组
    再详细点:

    (其中绿色为树状数组,红色为原数组)
    我们令树状数组为(C),原数组为(a),利用上图不难发现:
    ( C_1=a_1\ C_2=a_1+a_2\ C_3=a_3\ C_4=a_1+a_2+a_3+a_4\ C_5=a_5\ C_6=a_5+a_6\ C_7=a_7\ C_8=a_1+a_2+a_3+a_4+a_5+a_6+a_7+a_8 )
    可以发现,这颗树是有规律的:
    (C[i]=a[i-2^k+1]+a[i-2^k+2]+... +a[i];//k为i的二进制中从右往左第一位非0的位置)
    那么问题来了:如何求(2^k)
    先给个结论:(2^k)=(i)&((-i))
    咱们来看看Xenny大佬的解释:

    于是可以写出代码:

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

    有了以上基础,便可进入正题了(若不理解则多看几遍)

    单点更新,区间查询

    上面提到了:(C[i]=a[i-2^k+1]+a[i-2^k+2]+... +a[i])
    那么如果我们更新某个(a[i])的值,则会影响到所有包含有(a[i])(C数组)
    稍微思考可知:(a[i])包含于(C[i+2^k]、C[(i+2^k)+2^k]...)
    这便是更新和求和
    如果你弄懂了上面的内容,代码应该也很好理解了:

    int lowbit(int x)
    {
    	return x&(-x);
    }
    void updata(int x,int y)//表示将a[x]+y
    {
    	for(int i=x;i<=n;i+=lowbit(i))a[i]+=y;//更新
    }
    int getsum(int x)//表示a[1~x]的总和
    {
    	int ans=0;
    	for(int i=x;i>=1;i-=lowbit(i))ans+=a[i];//求和
    	return ans;
    }
    

    所以区间 ((x,y)) 的值为 (getsum(y)-getsum(x-1))
    更新和求和的时间复杂度:(Theta(log n))
    练习题:
    1
    2
    3

    区间更新,单点查询

    代码并不会变,只是多了个用差分建树
    假设有个(a)数组:

    我们要把(3)~(6)的数加(2),可直接将(a[3]+2,a[7]-2)
    (a)变为

    这样要求每个值时,则只需让一个变量跑一遍累加即可
    伪代码:

    a[x]+=z;a[y+1]-=z;
    for i:=1 to n do
      sum+=a[i],
      write(sum,' ');
    

    把差分用到树状数组中便可打出如下代码:

    void add(int l,int r,int x)//对l到r的数累加x,差分
    {
    	update(l,x);update(r+1,-x);
    }
    

    练习:
    1

    参考资料

    https://zhuanlan.zhihu.com/p/93795692
    https://blog.csdn.net/bestsort/article/details/80796531
    https://www.cnblogs.com/xenny/p/9739600.html
    https://www.luogu.com.cn/blog/BotDand/shu-zhuang-shuo-zu-xue-xi-bi-ji
    以及某人的PPT下载链接

    练习

    1
    2
    3

  • 相关阅读:
    easyui datagrid 编辑器绑定事件
    Java初学(八)
    Java初学(七)
    Java初学(六)
    Java初学(五)
    Java初学(四)
    GCC基本知识
    OpenCL memory object 之 Global memory (2)
    OpenCL memory object 之 Global memory (1)
    OpenCL memory object 之 传输优化
  • 原文地址:https://www.cnblogs.com/wuzhenhao/p/14978827.html
Copyright © 2011-2022 走看看