2017暑假训练第九天

  上午刚刚看完了树状数组的知识点,就自己的理解先做一下总结,整理一下学到了什么。

  树状数组:

  1.树状数组的作用--使用背景:

  当要同时存在下述两种操作数次的时候:

  1)对第x位置处的数据进行除了删除,乘除,之外的修改(比如增加或减去一个数)

  2)求某一位置的前缀和。

  处理以上两种情况的时候,使用简单的数组就不在适用了。(简单数组指的是a[]直接存某一位置的数是多少的数组以及sum[]存某个位置前缀和的数组)

  2.处理方法:

  建立树状数组。

  3.引入概念:

  与(&):int lowbit(int i){  return (i&(-i));}

  这个lowbit函数所得到的数是树状数组c[]和a[]以及sum[]之间的重要桥梁。

  4.具体关系:

  1)树状数组元素c[i]=a[i-lowbit(i)+1]+.......a[i]。

  2)数组a[i]存在于c[i],c[i=i+lowbit(i)],c[i+lowbit(i)].....中。

  3)数组sum[i]=c[i]+c[i-lowbit(i)]+.....。

  5.可推广性,对于多维的数组,只需每一维都执行如上操作即可。

  刚刚又看完了线段树的知识点,结合上述树状数组的知识点做一下简单的总结。

  线段树:

  1.线段树的作用--使用背景:

  当同时存在如下两种操作数次的时候:

  1)对区间的最大值或者区间和进行查询或者修改。

  2)对点的值进行查询和修改时。

  处理以上两种情况,区间问题会让时间复杂度变得极为复杂。

  2.处理方法:

  建立线段树。

  3.具体关系:

  线段树是把原存点的数组a[]处理成树状关系,以结构体数组的方式再行存储。

  4.线段树的具体使用:

  树的建立代码如下:

  void build(int id,int l,int r){

    tree[id].left=l;

    tree[id].right=r;

    if (l==r){

      tree[id].sum=a[r];

      tree[id].max=a[r];

    }

    else {

      int mid=(l+r)/2;

      build (2*id,l,mid);

      build (2*id+1,mid+1,r);

      tree[id].sum=tree[2*id].sum+tree[2*id+1].sum;

      tree[id].max=max(tree[2*id].max,tree[2*id+1].max);

    }

   注意到编号为i的树结点的sum和max仅仅和他的孩子i*2以及i*2+1这两个子节点有关系,树的更新和查找操作也正是利用了这点。

  5.总结:

  线段树适用于区间操作,而树状数组适用于前缀和操作,二者各有优劣,树状数组空间较小,但处理范围同样也小,线段树恰恰相反

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值