线段树模板

Posted PoorLitt1eThin9

tags:

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

template <class T> class SegmentTree {
    public:
        T dat;
        int leftBorder = -1;
        int rightBorder = -1;
        SegmentTree * leftSon = NULL;
        SegmentTree * rightSon = NULL;
        void Build(T *, int, int, T (*)(T, T));
        void Modify(int , T , T (*)(T, T));
        T Query(int, int, T (*)(T, T));
        void Free();
};
template<class T> void SegmentTree<T>::Build(T * S, int l, int r, T (* funptr)(T, T)) {
    if (l > r) {
        return;
    }
    leftBorder = l;
    rightBorder = r;
    if (l == r) {
        dat = S[l];
        return;
    }
    int mid = (l + r) >> 1;
    leftSon = new SegmentTree;
    leftSon->Build(S, l, mid, funptr);
    rightSon = new SegmentTree;
    rightSon->Build(S, mid + 1, r, funptr);
    dat = funptr(leftSon->dat, rightSon->dat);
}
template<class T> void SegmentTree<T>::Modify(int pos, T NewDat, T (* funptr)(T, T)) {
    if (pos < leftBorder || rightBorder < pos) {
        return;
    }
    if (leftBorder == rightBorder) {
        dat = NewDat;
        return;
    }
    int mid = (leftBorder + rightBorder) >> 1;
    if (pos <= mid) {
        leftSon->Modify(pos, NewDat, funptr);
    } else {
        rightSon->Modify(pos, NewDat, funptr);
    }
    dat = funptr(leftSon->dat, rightSon->dat);
}
template<class T> T SegmentTree<T>::Query(int l, int r, T(* funptr)(T, T)) {
    if (l < leftBorder || rightBorder < l ||
            r < leftBorder || rightBorder < r ||
            l > r) {
        return dat;
    }
    if (l == leftBorder && r == rightBorder) {
        return dat;
    }
    int mid = (leftBorder + rightBorder) >> 1;
    if (mid < l) {
        return rightSon->Query(l, r, funptr);
    }
    if (r <= mid) {
        return leftSon->Query(l, r, funptr);
    }
    return funptr(leftSon->Query(l, mid, funptr), rightSon->Query(mid + 1, r, funptr));
}
template<class T> void SegmentTree<T>::Free() {
    if (leftSon != NULL) {
        leftSon->Free();
    }
    if (rightSon != NULL) {
        rightSon->Free();
    }
    delete leftSon;
    delete rightSon;
}

SegmentTree<T> Tree:线段树Tree,基础类型为T。

Tree.dat:该节点存储的信息。

Tree.leftBorder/rightBorder:该节点线段的左右端点。

Tree.leftSon/rightSon:该线段树的左右子树指针。

Tree.Build:对T类型数组S上从l到r的部分建立线段树,并使用funptr函数根据两子树的dat计算出该节点的dat。

Tree.Modify:将对应原数组pos位置的值修改为NewDat,并使用funptr函数调整相关节点的dat值。

Tree.Query:询问对应原数组从l到r部分的dat值。

Tree.Free:释放线段树所使用的内存。

funptr函数需要自己定义。

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

线段树模板整理

线段树模板总结

线段树模板

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

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

模板 线段树(部分功能)