c++ 线段树的优雅实现

#include <iostream>
#include <vector>
using namespace  std;

const static int MAX_N = 1 << 17;

int n, dat[MAX_N - 1];

/*
 *  将 n变成 2的幂次 的好处是这样, 最终所有的单区间值都在最下层, 方便修改值
 *
 * */
void init(int _n) {
    n = 1;
    while (n < _n) {
        n <<= 1;
    }
    for (int i = 0; i < 2 * n - 1; ++i) {
        dat[i] = INT_MAX;
    }
}

void update(int index, int v) {
    index += n - 1;
    dat[index] = v;
    while (index > 0) {
        index = (index - 1) / 2;
        dat[index] = min(dat[2 * index + 1], dat[2 * index + 2]);
    }
}

int query(int ql, int qr,int node = 0, int left =  0, int right =  n - 1) {
    if (ql > right || qr < left) {
        return INT_MAX;
    }
    if (ql <= left && qr >= right) {
        return dat[node];
    } else {
        int lv = query(ql, qr, 2 * node + 1, left, (left + right) / 2);
        int rv = query(ql, qr, 2 * node + 2, (left + right) / 2 + 1, right);
        return min(lv, rv);
    }
}


int main() {
    vector<int> nums{3, 2, 4, 7};
    init(nums.size());
    for (int i = 0; i < nums.size(); ++i) {
        update(i, nums[i]);
    }
    update(3, 3);
    for (int i = 0; i < 2 * n - 1; ++i) {
        cout << dat[i] << " ";
    }
    cout << endl;

    return 0;
}

class SegmentTree{
public:
    int n;
    vector<int> tree;

    SegmentTree(int sz) {
        n = 1;
        while (n < sz) n <<= 1;
        tree.resize(n * 2, INT_MAX);
    }

    void update(int i, int val) {
        i += (n - 1);
        tree[i] = val;
        while (i > 0) {
            int p = (i - 1) / 2;
            tree[p] = min(tree[(p << 1) + 1], tree[(p << 1) + 2]);
            i = p;
        }
    }

    int query(int L, int R) {
        int left = n - 1, right = 2 * (n - 1);
        L += n - 1;
        R += n - 1;
        return _query(left, right, 0, L, R);
    }

    int _query(int left, int right, int nodeId, int L, int R) {
        if (L <= left && right <= R) {
            return tree[nodeId];
        }
        int mid = (left + right) / 2;
        if (mid >= R) {
            return _query(left, mid, (nodeId << 1) + 1, L, R);
        } else if (mid < L) {
            return _query(mid + 1, right, (nodeId << 1) + 2, L, R);
        }
        return min(_query(left, mid, (nodeId << 1) + 1, L, R), _query(mid + 1, right, (nodeId << 1) + 2, L, R));
    }
};

int main() {
    vector<int> data = {0, 1, -1, -3, -5, -7, -8};
    int n = data.size();
    SegmentTree tree(n);
    for (int i = 0; i < n; i++) {
        tree.update(i, data[i]);
    }
    for (int i = 0; i < n; i++) {
        for (int j = i; j < n; j++) {
            cout << tree.query(i, j) << " ";
        }
        cout << endl;
    }
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值