[hiho 19]单点修改的线段树

问题描述

依然是RMQ问题。过程需要修改某些点的数据。

使用线段树解决。

单点修改的复杂度是O(logn),即树深,只需要修改这个点的祖先节点。

区间查询的复杂度也是O(logn),因为除了第一步可能一分为二外,其他查询若有分解则分解后必然有一个区间是不需要再分解的。

#include <stdio.h>
#include <algorithm>

typedef
struct _seg_tree_ {
    int left, right;
    int val;
    _seg_tree_ *lson = NULL, *rson = NULL;
    _seg_tree_(int left_idx, int right_idx, int value)
        : left(left_idx), right(right_idx), val(value) {}
} seg_tree, *pseg_tree;

pseg_tree construct_seg_tree(int left, int right) {
    if (left == right) {
        int val;
        scanf("%d", &val);
        return new seg_tree(left, left, val);
    }
    int mid = left + (right - left) / 2;
    pseg_tree lson = construct_seg_tree(left, mid);
    pseg_tree rson = construct_seg_tree(mid + 1, right);
    int val = std::min(lson->val, rson->val);
    pseg_tree ans = new seg_tree(left, right, val);
    ans->lson = lson;
    ans->rson = rson;
    return ans;
}

int query_seg_tree(pseg_tree proot, int left, int right) {
    if (left == proot->left && right == proot->right) {
        return proot->val;
    }
    int mid = proot->left + (proot->right - proot->left) / 2;
    if (left > mid) {
        return query_seg_tree(proot->rson, left, right);
    }
    if (right <= mid) {
        return query_seg_tree(proot->lson, left, right);
    }
    return std::min(query_seg_tree(proot->lson, left, mid),
                    query_seg_tree(proot->rson, mid + 1, right));
}

void modify_seg_tree(pseg_tree proot, int left, int val) {
    if (left == proot->left && left == proot->right) {
        proot->val = val;
        return;
    }
    int mid = proot->left + (proot->right - proot->left) / 2;
    if (left > mid) {
        modify_seg_tree(proot->rson, left, val);
    } else {
        modify_seg_tree(proot->lson, left, val);
    }
    proot->val = std::min(proot->lson->val, proot->rson->val);
}

int main(){
    int n, q;
    scanf("%d", &n);
    pseg_tree proot = construct_seg_tree(1, n);
    scanf("%d", &q);
    int op, left, right;
    while (q--) {
        scanf("%d%d%d", &op, &left, &right);
        if (op == 0) {
            int ans = query_seg_tree(proot, left, right);
            printf("%d\n", ans);
        } else {
            modify_seg_tree(proot, left, right);
        }
    }

    return 0;
}

转载于:https://www.cnblogs.com/xblade/p/4503101.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值