线段树

介绍:

过多就不赘述了

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

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

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

只有唯一的根结点。

叶子节点代表一个数,或者长度为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);
    ......;
}

 

扫描线:

......

 

posted @ 2020-07-24 21:44  愚者123  阅读(101)  评论(0)    收藏  举报