线段树算法c++模板

线段树是一种非常强大的数据结构,用于解决区间查询和更新问题。它允许你对一个数组的子区间执行各种操作,如求和、求最小值、求最大值等。以下是一个C++模板,展示了如何实现线段树。

#include <iostream>
#include <vector>
#include <algorithm>

// 线段树的实现
template<typename T>
class SegmentTree {
private:
    std::vector<T> tree; // 线段树的数组表示
    int n; // 数组的大小

    // 合并两个元素,可以是求和、求最大值等
    T merge(T a, T b) {
        return a + b; // 示例使用求和
    }

    // 构建线段树
    void build(int node, int start, int end, const std::vector<T>& arr) {
        if (start == end) {
            tree[node] = arr[start];
        } else {
            int mid = (start + end) / 2;
            build(2 * node, start, mid, arr);
            build(2 * node + 1, mid + 1, end, arr);
            tree[node] = merge(tree[2 * node], tree[2 * node + 1]);
        }
    }

    // 区间查询
    T query(int node, int start, int end, int l, int r) {
        if (r < start || end < l) {
            return 0; // 返回一个合适的默认值,例如求和为0
        }
        if (l <= start && end <= r) {
            return tree[node];
        }
        int mid = (start + end) / 2;
        T left_result = query(2 * node, start, mid, l, r);
        T right_result = query(2 * node + 1, mid + 1, end, l, r);
        return merge(left_result, right_result);
    }

    // 点更新
    void update(int node, int start, int end, int idx, T val) {
        if (start == end) {
            tree[node] = val;
        } else {
            int mid = (start + end) / 2;
            if (idx <= mid) {
                update(2 * node, start, mid, idx, val);
            } else {
                update(2 * node + 1, mid + 1, end, idx, val);
            }
            tree[node] = merge(tree[2 * node], tree[2 * node + 1]);
        }
    }

public:
    // 构造函数,接收一个数组作为输入,建立线段树
    SegmentTree(const std::vector<T>& arr) {
        n = arr.size();
        tree.resize(4 * n);
        build(1, 0, n - 1, arr);
    }

    // 查询区间[l, r]的结果
    T query(int l, int r) {
        return query(1, 0, n - 1, l, r);
    }

    // 更新位置idx的值为val
    void update(int idx, T val) {
        update(1, 0, n - 1, idx, val);
    }
};

int main() {
    // 示例用法
    std::vector<int> arr = {1, 3, 5, 7, 9, 11};
    SegmentTree<int> st(arr);
    std::cout << "Sum in range [1, 3]: " << st.query(1, 3) << std::endl;
    st.update(1, 10); // 将arr[1]更新为10
    std::cout << "Sum in range [1, 3] after update: " << st.query(1, 3) << std::endl;
    return 0;
}

在这个模板中,我们使用一个数组tree来表示线段树。每个节点node表示区间[start, end]的合并结果。对于求和操作,merge函数返回两个子区间的和;对于求最大值或最小值操作,merge函数返回相应的最大或最小值。

构造函数SegmentTree接受一个数组作为输入,然后调用build函数来递归地构建线段树。

query函数用于查询区间[l, r]的合并结果。如果查询区间完全在当前节点的代表区间内部,我们直接返回该节点的值。如果查询区间与当前节点的代表区间相交,我们递归地查询两个子节点,并将结果合并后返回。

update函数用于更新数组中某个位置的值。我们首先更新叶节点的值,然后递归地更新父节点的值,直到根节点。

请注意,这个模板假设数组是从0开始索引的。如果你的数组是从1开始索引的,你可能需要对代码进行一定的调整。此外,根据你的具体需求,你可能需要修改merge函数来执行不同的操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值