线段树

线段树


主要由五个操作:
pushup():由子节点算父节点的信息。例如计算当前区间的总和,父亲节点等于左右两个结点的区间之和
pushdown():由父节点传递给子节点的信息。也被称为懒标记。
build():将一段区间初始化为线段树
modify():修改某一个点或者某一个区间
query():查询某一段区间的信息

一般使用一维数组存整棵树。从编号为1开始存储
编号为x的父亲结点x/2,左儿子:2*x,右儿子:2*x+1
其中有n个叶子节点。最坏的情况下会有4*n-1个点,所以一般的情况下会开4n个结点

void build(int u,int l,int r){//当前结点编号,左右孩子编号 
  tr[u].l=l,tr[u].r=r;
  if(l==r) {
  //如果需要在叶子结点存储来自输入的信息,可以直接在这里cin>>
  return;
  }
int mid=l+r>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
pushup(u);
}

查询分为2种情况,需要查询的区间[L,R],当前访问的线段树区间[l,r]
1:L<=l,R>=r,直接返回当前区间的信息就可以了,不用继续向下搜索了
2:只有一部分存在交集。

单点修改不需要懒标记

懒标记:pushdown()
扫描线法

懒标记:加上懒标记可以完成区间修改的操作。跟区间查询的操作类似。修改一个区间,当遇到一个完成的区间的时候,就标记这个区间,并返回,不继续向下继续修改
给以当前结点为根的子树中的每一个结点都包含这个懒标记,/*但是当前区间结点并不包括*/

一般而言,pushup()需要放在build()和modify()的后面。
pushdown()放在modify()和query()的前面

除了build()之外,其他的函数的区间直接向下传递l,r不用传递mid

void pushup(int u){
    tr[u].v=max(tr[u<<1].v,tr[u<<1|1].v);
}
int query(int u,int l,int r){
    if(tr[u].l>=l&&tr[u].r<=r) return tr[u].v;
    int v=0;
    int mid=tr[u].l+tr[u].r>>1;
    if(l<=mid) v=query(u<<1,l,r);
    if(r>mid) v=max(v,query(u<<1|1,l,r));
    return v; 
}
void modify(int u,int x,int d){ //这是最简单的一个modify,因为这是单点修改 
    if(tr[u].l==x&&tr[u].r==x) {
        tr[u].v=d;
        return ;
    }
    else {
        int mid=tr[u].l+tr[u].r>>1;
        if(x<=mid) modify(u<<1,x,d);
        if(x>mid) modify(u<<1|1,x,d);
        pushup(u);
    }
}
void modify(int u,int x,ll d){//区间修改
    if(tr[u].l==x&&tr[u].r==x){
        tr[u].gc+=d;
        return ;
    }
    int mid=tr[u].l+tr[u].r>>1;
    if(x<=mid) modify(u<<1,x,d);
    if(x>mid) modify(u<<1|1,x,d);
    pushup(u);
    return ;
}
void pushdown(int u){
    if(tr[u].add!=0){
        tr[u<<1].sum+=(tr[u<<1].r-tr[u<<1].l+1)*tr[u].add;
        tr[u<<1].add+=tr[u].add;
        tr[u<<1|1].sum+=(tr[u<<1|1].r-tr[u<<1|1].l+1)*tr[u].add;
        tr[u<<1|1].add+=tr[u].add;
        tr[u].add=0;
    }
}

写于:2020/8/29  22:40


作者:孙建钊
出处:http://www.cnblogs.com/sunjianzhao/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文地址:https://www.cnblogs.com/sunjianzhao/p/13583842.html