线段树模板

Posted alessandro

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树模板相关的知识,希望对你有一定的参考价值。

线段树教程

代码

struct Seg {
    int l, r, sum, lazy, add;
    // lazy == -1: mo dei biao ji
    Seg *ch[2];
};

Seg pool[maxn * 3], *pool_pointer(pool);

#define midp ((p->l+p->r)>>1)

inline void update(Seg* p) {
    if (p->lazy != -1) {
        p->sum = (p->r - p->l) * p->lazy;
    } else {
        p->sum = p->ch[0]->sum + p->ch[1]->sum + p->add * (p->r - p->l);
    }
}

Seg* segTreeBuild(int l, int r) {
    Seg* p = pool_pointer + 1;
    p->l = l, p->r = r;
    if (l + 1 < r) {
        p->ch[0] = segTreeBuild(l, midp);
        p->ch[1] = segTreeBuild(midp, r);
        update(p);
    } else {
        p->sum = a[l];
        p->lazy = -1;
    }
    return p;
}

void segTreeChangeOne(Seg* p, int pos, int val) {
    if (p->l + 1 == p->r) {
        p->sum = val;
    } else {
        if (pos < midp) {
            segTreeChangeOne(p->ch[0], pos, val);
        } else {
            segTreeChangeOne(p->ch[1], pos, val);
        }
        update(p);
    }
}

inline void pushDown(Seg* p) {
    if (p->lazy != -1) {
        p->ch[0]->lazy = p->lazy;
        p->ch[1]->lazy = p->lazy;
        update(p->ch[0]);
        update(p->ch[1]);
        p->lazy = -1;
    }
    if (p->add > 0) {
        p->ch[0]->add += p->add;
        p->ch[1]->add += p->add;
        update(p->ch[0]);
        update(p->ch[1]);
        p->add = 0;
    }
}

void segTreeChangeRange(Seg* p, int l, int r, int val) {
    if (p->l == l && p->r == r) {
        p->lazy = val;
        p->sum = (r - l) * val;
    } else {
        pushDown(p);
        if (r <= midp) {
            segTreeChangeRange(p->ch[0], l, r, val);
        } else if (l >= midp) {
            segTreeChangeRange(p->ch[1], l, r, val);
        } else {
            segTreeChangeRange(p->ch[0], l, midp, val), segTreeChangeRange(p->ch[1], midp, r, val);
        }
        update(p);
    }
}

int segTreeSum(Seg* p, int l, int r) {
    if (p->l == l && p->r == r) {
        return p->sum;
    } else {
        if (r <= midp) {
            return segTreeSum(p->ch[0], l, r);
        } else if (l >= midp) {
            return segTreeSum(p->ch[1], l, r);
        } else {
            return segTreeSum(p->ch[0], l, midp) + segTreeSum(p->ch[1], midp, r);
        }
    }
}

以上是关于线段树模板的主要内容,如果未能解决你的问题,请参考以下文章

线段树模板整理

线段树模板总结

线段树模板

模板线段树-单点修改,区间查询

P3834 模板可持久化线段树 1(主席树)

模板 线段树(部分功能)