zoukankan      html  css  js  c++  java
  • 线段树

    介绍:

    过多就不赘述了

    它与树状数组相比,更加灵活,但码量大,容易写错。

    它每一个节点代表一个区间。

    每一个节点分左端和右端。

    只有唯一的根结点。

    叶子节点代表一个数,或者长度为1的区间。

    对于每一个节点(区间【l,r】)左节点为【l,mid】,右节点为【mid+1,r】。

    实际上除去所有叶子节点,它就是一个完全二叉树

    假设它是一个满二叉树,它所要开的区间要为 4N 以上,防止越界。

    过程:

    建树-

    struct node{
        long l,r;
        long d;
    }t[4*N];
    
    inline void build(long p,long l,long r){
        t[p].l=l,t[p].r=r;
        if(t[p].l==t[p].r) {
        t[p].d=a[l];
        return ;
        }
        long mid=(l+r)>>1;
        build(p*2,l,mid);
        build(p*2+1,mid+1,r);
        t[p].d=max(t[p*2].d,t[p*2+1].d);
    }
    
    // build(1,1,n); // 其中t[p].d为区间最大值

    单点修改:

    inline void change(long p,long x,long z){
        if(t[p].l==t[p].r) {
        a[p].d=z;
        return ;    
        }
        long mid=(t[p].l+t[p].r)>>1;
        if(x<=mid) change(p*2,x,z);
        else change(p*2+1,x,z);
        t[p].d=max(t[p*2].d,t[p*2+1].d);
    }
    
    //change(1,x,z);

    区间查询:

    long ask(long p,long l,long r){
        if(l<=t[p].l && r>=t[p].r) return t[p].d;
        long mid=(t[p].l+t[p].r)>>1;
        long minn=-(1<<30);
        if(l<=mid) minn=max(minn,ask(p*2,l,r));
        if(r>mid) minn=max(minn,ask(p*2+1,l,r));
        return minn;
    }
    
    // long answer=ask(1,l,r);

    这个过程需要自己模拟一遍就懂了

    详细不再赘述。

    区间修改:

    inline void _change(long p,long l,long r,long z){
        if(l<=t[p].l && r>=t[p].r) {
        t[p].sum+=(t[p].r-t[p].l+1)*z;
        return ;
        }
        if(l<=mid) _change(p*2,l,r,z);
        if(r>mid) _change(p*2+1,l,r,z);
        t[p].sum=t[p*2].sum+t[p*2+1].sum;
    }

    懒惰标记(延迟标记,lazy):

    因为我们每一次进行区间修改,如果每一个点都去一个个地更新,复杂度相对较高,而且我们其实可以发现,在后续查询中,不一定会用到这些辛辛苦苦修改过的点,所以我们可以先给这个点打上标记,记录修改多少,记住自身应先修改,然后用到它的子树的时候再将标记下推。

    inline void spread (long p){
        if(t[p].lazy){
        t[p*2].sum+=t[p].lazy*(t[p*2].r-t[p*2].l+1);
        t[p*2+1].sum+=t[p].lazy*(t[p*2+1].r-t[p*2+1].l+1);
        t[p*2].lazy+=t[p].lazy;
        t[p*2+1].lazy+=t[p].lazy;
        t[p].lazy=0;
        }    
    }
    inline void _change(long p,long l,long r,long z){
        if(......){
        ......;
        t[p].lazy+=z;
        return ;
        }
        spread(p);
        ......
    }
    long ask(long p,long l,long r){
        if(......)......;
        spread(p);
        ......;
    }

    扫描线:

    ......

  • 相关阅读:
    Word 语法高亮
    AsyncFileUpload+Editor
    Silverlight QQ
    网页变黑白…
    Accelerator in Internet Explorer 8
    VS2010中文版安装Silverlight4 Tools…
    Win7下要求以管理员权限运行程序
    AjaxControlToolkitSeaDragon
    WebSlices in Internet Explorer 8
    <当和尚遇到钻石>读书笔记
  • 原文地址:https://www.cnblogs.com/yuzhe123/p/13374724.html
Copyright © 2011-2022 走看看