线段树模板

[亡魂溺海] 提交于 2019-11-29 07:05:16

不要当线段树都不会敲的菜鸡了。

线段树所要提供的是查询一个区间 

 内的信息

,并允许修改操作。

 节点数据向上更新

对于区间求和:

void push_up(int rt){
    tree[rt] = tree[rt<<1] + tree[rt<<1|1];
}

对于区间求最值:

void push_up(int rt){
    tree[rt] = max(tree[rt<<1],tree[rt<<1|1]);
}

 节点懒惰标记向下传递

对于区间求和:

void push_down(int rt,int len){
    tree[rt<<1] += lazy[rt]*( len-(len>>1) );
    lazy[rt<<1] += lazy[rt];
    tree[rt<<1|1] += lazy[rt]*(len>>1);
    lazy[rt<<1|1] += lazy[rt];
    lazy[rt]=0;
}

对于区间求最值:

void push_down(int rt){
    tree[rt<<1] += lazy[rt];
    lazy[rt<<1] += lazy[rt];
    tree[rt<<1|1] += lazy[rt];
    lazy[rt<<1|1] += lazy[rt];
    lazy[rt] = 0;
}

建树

void build(int l,int r,int rt){
    lazy[rt] = 0;
    if(l==r){
        tree[rt] = 0;
    }
    int m = l+r>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    push_up(rt);
}

更新:

void update(int ql,int qr,int l,int r,int rt,int val){
    if(ql<=l && qr>=r){
        tree[rt] += val*(r-l+1);
        lazy[rt] += val;
        return;
    }
    if(lazy[rt])
        push_down(rt,r-l+1);
    int m = l+r>>1;
    if(ql<=m)
        update(ql,qr,l,m,rt<<1,val);
    if(qr>m)
        update(ql,qr,m+1,r,rt<<1|1,val);
    push_up(rt);
}

查询:

ll query(int ql,int qr,int l,int r,int rt){
    if(ql<=l && qr>=r) return tree[rt];
    if(lazy[rt])
        push_down(rt,r-l+1);
    int m = l+r>>1;
    int res=0;
    if(ql<=m)
        res += query(ql,qr,l,m,rt<<1);
    if(qr>m)
        res += query(ql,qr,m+1,r,rt<<1|1);
    return res;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!