依然是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;
}