C++线段树模板(区间和、区间加)

操作说明:

  • segtree<T>tree(len) =>创建一个内部元素类型为T、区间为1~len的线段树tree
  • tree.build(l,r) =>以[l,r]区间建立线段树
  • tree.update(l,r,val,1,len) =>区间[l,r]所有元素加上val
  • tree.query(l,r,1,len) =>计算区间[l,r]的元素和
#include <iostream>
#include <string>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <deque>
#include <map>
#define range(i,a,b) for(auto i=a;i<=b;++i)
#define LL long long
#define itrange(i,a,b) for(auto i=a;i!=b;++i)
#define rerange(i,a,b) for(auto i=a;i>=b;--i)
#define fill(arr,tmp) memset(arr,tmp,sizeof(arr))
using namespace std;
template <class T>
class segtree{
private:
    T* add,*sum;
    void pushup(int rt){
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    }
    void pushdown(int rt,int m){
        if(add[rt]){
            add[rt<<1]+=add[rt];
            add[rt<<1|1]+=add[rt];
            sum[rt<<1]+=add[rt]*(m-(m>>1));
            sum[rt<<1|1]+=add[rt]*(m>>1);
            add[rt]=0;
        }
    }
public:
    explicit segtree(int len=int(1e5+5)){
        add=new T[len<<2];
        sum=new T[len<<2];
        fill(add,0);fill(sum,0);
    }
    void build(int l,int r,int rt=1){
        add[rt]=0;
        if(l==r){
            sum[rt]=0;
            return;
        }
        int m=(l+r)>>1;
        build(l,m,rt<<1);
        build(m+1,r,rt<<1|1);
        pushup(rt);
    }
    void update(int L,int R,T c,int l,int r,int rt=1){
        if(L<=l&&r<=R){
            add[rt]+=c;
            sum[rt]+=c*(r-l+1);
            return;
        }
        pushdown(rt,r-l+1);
        int m=(l+r)>>1;
        if(L<=m)update(L,R,c,l,m,rt<<1);
        if(m<R)update(L,R,c,m+1,r,rt<<1|1);
        pushup(rt);
    }
    T query(int L,int R,int l,int r,int rt=1){
        if(L<=l&&r<=R)return sum[rt];
        pushdown(rt,r-l+1);
        int m=(l+r)>>1;
        T ret=0;
        if(L<=m)ret+=query(L,R,l,m,rt<<1);
        if(m<R)ret+=query(L,R,m+1,r,rt<<1|1);
        return ret;
    }
};
int main() {
    segtree<int>tree(10);
    tree.build(1,10);
    tree.update(1,5,1,1,10);
    cout<<tree.query(1,5,1,10)<<endl;
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/Rhythm-/p/9373052.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值