SCL -- 线段树

2015-07-15 21:30:57

总结:线段树的题做了这么多,来总结个最典型的区间加法的线段树。

  

const int MAXN = 100010;

int N,Q;
int A[MAXN];

struct SMT{
    ll tsum[MAXN << 2],add[MAXN << 2],len[MAXN << 2];
    void build(int p,int l,int r){
        len[p] = r - l + 1;
        if(l == r){
            tsum[p] = A[l];
            add[p] = 0;
            return;
        }
        int mid = getmid(l,r);
        build(p << 1,l,mid);
        build(p << 1|1,mid + 1,r);
        push_up(p);
    }
    inline void push_up(int p){
        tsum[p] = tsum[p << 1] + tsum[p << 1|1];
    }
    inline void push_down(int p){
        if(add[p]){
            add[p << 1] += add[p];
            tsum[p << 1] += add[p] * len[p << 1];
            add[p << 1|1] += add[p];
            tsum[p << 1|1] += add[p] * len[p << 1|1];
            add[p] = 0;
        }
    }
    void update(int a,int b,int c,int p,int l,int r){
        if(a <= l && r <= b){
            add[p] += c;
            tsum[p] += c * len[p];
            return;
        }
        push_down(p);
        int mid = getmid(l,r);
        if(a <= mid) update(a,b,c,p << 1,l,mid);
        if(b > mid) update(a,b,c,p << 1|1,mid + 1,r);
        push_up(p);
    }
    ll query(int a,int b,int p,int l,int r){
        if(a <= l && r <= b){
            return tsum[p];
        }
        push_down(p);
        int mid = getmid(l,r);
        ll res = 0;
        if(a <= mid) res += query(a,b,p << 1,l,mid);
        if(b > mid) res += query(a,b,p << 1|1,mid + 1,r);
        return res;
    }
}smt;

 

posted @ 2015-07-15 21:33  Naturain  阅读(121)  评论(0编辑  收藏  举报