zoukankan      html  css  js  c++  java
  • 浅谈zkw线段树(by Shine_hale)

    线段树嘛,很好用的数据结构处理方法但是有个缺点

    代码长,不好理解,但是很强大

    其建树方法是递归建树,调用栈来运行,从上至下,有人说,这类似一个回溯的过程

    其实也不然,标记下放后,标记仍需上浮,一上一下,自然速度会很大的降低

    那么有没有从下而上的操作呢?

    zkw神犇出现了,“哈哈,我会”

    zkw线段树从此诞生了,zkw线段树有很多用途,正在被开发,适用范围没有普通线段树广,但是其处理单标记问题,是比普通线段树快一倍以上,甚好甚好

    于是蒟蒻的hale查看了各方大佬的博客,以及zkw大佬本人的2013年发表的《统计的力量》虽说我看不懂吧,总算搞懂了一点点

    今天给大家讲的就是初步的建树方法,以及区间修改区间求和,嘤嘤嘤

    一、 

    建树原理请参加《统计的力量》,图我就不给大家放上来了,我相信各位可以看懂至少他的建树原理吧

    直接贴上代码了

    void push_up(int p)
    { st[p].ans=st[ls(p)].ans+st[rs(p)].ans;}
    void build()
    { for (M=1;M<=n+1;M<<=1);
      for (int i=M+1;i<=M+n;i++)
      scanf("%lld",&st[i].ans);
      for (int i=M-1;i;i--)
      push_up(i);
    }

    二、区间修改

    zkw线段树主要不同于普通线段树,我认为不是他的非递归建树

    而是他的标记永久化以及自底往上的标记上浮原理,这才是他速度快的核心

    我不会告诉你我理解这花了一天时间,嘤嘤嘤

    首先你要把你的区间做成开区间

    nl表示左指针走了多少了

    nr表示右指针走了多少了

    x表示这层的点的子树多大

    然后大家画个图理解一下了

    还是很容易的不是吗

    void update(int l,int r,ll k)
    { int s=M+l-1,t=M+r+1,nl=0,nr=0,x=1;
      for (;s^t^1;s>>=1,t>>=1,x<<=1)//这段for包含的信息有点多,还是耐心理解一下最好 
      { st[s].ans+=nl*k;
        st[t].ans+=nr*k;
        if (~s&1) {st[s^1].add+=k;st[s^1].ans+=k*x;nl+=x;}//处理左指针,若左指针是左儿子,则右儿子被修改 
        if (t&1)  {st[t^1].add+=k;st[t^1].ans+=k*x;nr+=x;}//处理右指针,若右指针是右儿子,则左儿子北修改 
      }
      for (;s;s>>=1,t>>=1)//一加到底,进行修改,防制gg 
      { st[s].ans+=k*nl;
        st[t].ans+=k*nr;
      }
    }

    三、区间求和

    原理跟更改差不多,就不一一赘述了

    直接贴代码,大家自己多想想就好了

    ll query(int l,int r)
    { int s=l+M-1,t=r+M+1,nl=0,nr=0,x=1;
      ll ans=0;
      for (;s^t^1;s>>=1,t>>=1,x<<=1)
      { if (st[s].add) ans+=st[s].add*nl;
        if (st[t].add) ans+=st[t].add*nr;
        if (~s&1) {ans+=st[s^1].ans;nl+=x;}
        if (t&1)  {ans+=st[t^1].ans;nr+=x;}
      }
      for (;s;s>>=1,t>>=1)
      { ans+=st[s].add*nl;
        ans+=st[t].add*nr;
      }
      return ans;
    }

    四、总结

    zkw线段树,真的好用,快捷,必要时可以考虑一下,很爽的,嘤嘤嘤

    其实《统计的力量》当中后面有很多新奇的玩法,奈何hale文化课压力太大,滚去学文化课了,望各位神犇学会后,教hale一下了

    最后的最后就是贴代码的时间了

    本题原型

    #include<bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    const int Ma=200010;
    int m,n,k,M;
    ll a[Ma];
    struct node
    { ll ans,add;} st[Ma<<1];
    int ls(int p) {return p<<1;}
    int rs(int p) {return p<<1|1;}
    void push_up(int p)
    { st[p].ans=st[ls(p)].ans+st[rs(p)].ans;}
    void build()
    { for (M=1;M<=n+1;M<<=1);
      for (int i=M+1;i<=M+n;i++)
      scanf("%lld",&st[i].ans);
      for (int i=M-1;i;i--)
      push_up(i);
    }
    void update(int l,int r,ll k)
    { int s=M+l-1,t=M+r+1,nl=0,nr=0,x=1;
      for (;s^t^1;s>>=1,t>>=1,x<<=1)//这段for包含的信息有点多,还是耐心理解一下最好 
      { st[s].ans+=nl*k;
        st[t].ans+=nr*k;
        if (~s&1) {st[s^1].add+=k;st[s^1].ans+=k*x;nl+=x;}//处理左指针,若左指针是左儿子,则右儿子被修改 
        if (t&1)  {st[t^1].add+=k;st[t^1].ans+=k*x;nr+=x;}//处理右指针,若右指针是右儿子,则左儿子北修改 
      }
      for (;s;s>>=1,t>>=1)//一加到底,进行修改,防制gg 
      { st[s].ans+=k*nl;
        st[t].ans+=k*nr;
      }
    }
    ll query(int l,int r)
    { int s=l+M-1,t=r+M+1,nl=0,nr=0,x=1;
      ll ans=0;
      for (;s^t^1;s>>=1,t>>=1,x<<=1)
      { if (st[s].add) ans+=st[s].add*nl;
        if (st[t].add) ans+=st[t].add*nr;
        if (~s&1) {ans+=st[s^1].ans;nl+=x;}
        if (t&1)  {ans+=st[t^1].ans;nr+=x;}
      }
      for (;s;s>>=1,t>>=1)
      { ans+=st[s].add*nl;
        ans+=st[t].add*nr;
      }
      return ans;
    }
    int main()
    { int x,y;ll z;
      scanf("%d%d",&n,&m);
      build();
      for (int i=1;i<=m;i++)
      { scanf("%d",&k);
        switch(k)
        { case 1:{scanf("%d%d%lld",&x,&y,&z);
                  update(x,y,z);
                  break;}
          case 2:{scanf("%d%d",&x,&y);
                  printf("%lld
    ",query(x,y));
                  break;}
        }
      }
      return 0;
    }
    慢即是快,细则是能,于小处铸迤逦
  • 相关阅读:
    手机管理中的应用【6】——电源管理篇
    NYOJ 14 场地安排(它可以被视为一个经典问题)
    YUV格式转换RGB(基于opencv)
    互联网金融进入洗礼阶段,控制风险是制胜之道
    Uva 409-Excuses, Excuses!(串)
    MATLAB新手教程
    IE无法打开internet网站已终止操作的解决的方法
    关于SetCapture() 和 ReleaseCapture()的使用方法
    wxWidgets刚開始学习的人导引(2)——下载、安装wxWidgets
    MyReport报表引擎2.7.6.7新功能
  • 原文地址:https://www.cnblogs.com/Hale522520/p/10198749.html
Copyright © 2011-2022 走看看