线段树模板

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

线段树所要提供的是查询一个区间 {\displaystyle [l,r)} 内的信息{\displaystyle f([l,r))},并允许修改操作。

 节点数据向上更新

对于区间求和:

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;
}

 

转载于:https://www.cnblogs.com/-Zzz-/p/11462591.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值