码迷,mamicode.com
首页 > 其他好文 > 详细

线段树模板

时间:2016-09-10 19:04:06      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:

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函数需要自己定义。

线段树模板

标签:

原文地址:http://www.cnblogs.com/dramstadt/p/5859846.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!