线段树(Segment Tree)是一种常见的数据结构,用于解决区间查询问题。最短线段树(Shortest Segment Tree)是线段树的一种变种,用于快速查询一个区间的最小值及其位置。本文将详细介绍最短线段树的原理、实现方法和应用场景。
一、原理
最短线段树的原理和普通线段树的原理类似,都是通过递归的方式将区间划分为更小的区间,然后在每个节点上维护一些信息。最短线段树在每个节点上维护区间的最小值和最小值的位置。当查询某个区间的最小值时,除了返回区间最小值,还可以返回该最小值在区间中的位置。
下面是最短线段树的一般实现流程:
-
将区间划分为更小的区间,直到每个区间只有一个元素。
-
在每个节点上维护该区间的最小值和最小值的位置。
-
查询某个区间的最小值及其位置时,从根节点开始向下递归,如果该节点所表示的区间完全包含查询区间,则直接返回该节点的最小值和最小值的位置;否则,分别递归左子树和右子树,然后合并两个子树的结果,返回合并后的最小值和最小值的位置。
-
修改某个位置的值时,从根节点开始向下递归,找到包含该位置的节点,更新该节点的最小值和最小值的位置,并继续向下递归,直到叶子节点。
二、实现
下面是最短线段树的具体实现代码(使用 C++ 实现):
#include <iostream>
#include <climits>
#include <algorithm>
using namespace std;
const int MAXN = 100000;
struct Node {
int min_val, min_pos;
};
int n;
int a[MAXN];
Node tree[4*MAXN];
void build(int idx, int l, int r) {
if (l == r) {
tree[idx].min_val = a[l];
tree[idx].min_pos = l;
} else {
int mid = (l+r)/2;
build(2*idx, l, mid);
build(2*idx+1, mid+1, r);
if (tree[2*idx].min_val <= tree[2*idx+1].min_val) {
tree[idx].min_val = tree[2*idx].min_val;
tree[idx].min_pos = tree[2*idx].min_pos;
} else {
tree[idx].min_val = tree[2*idx+1].min_val;
tree[idx].min_pos = tree[2*idx+1].min_pos;
}
}
}
Node query(int idx, int l, int r, int ql, int qr) {
if (l > qr || r < ql) {
return {INT_MAX, -1};
}
if (l >= ql && r <= qr) {
return tree[idx];
}
int mid = (l+r)/2;
Node left = query(2*idx, l, mid, ql, qr);
Node right = query(2*idx+1, mid+1, r, ql, qr);
if (left.min_val <= right.min_val) {
return left;
} else {
return right;
}
}
void update(int idx, int l, int r, int pos, int val) {
if (l == r) {
a[pos] = val;
tree[idx].min_val = val;
tree[idx].min_pos = pos;
} else {
int mid = (l+r)/2;
if (pos <= mid) {
update(2*idx, l, mid, pos, val);
} else {
update(2*idx+1, mid+1, r, pos, val);
}
if (tree[2*idx].min_val <= tree[2*idx+1].min_val) {
tree[idx].min_val = tree[2*idx].min_val;
tree[idx].min_pos = tree[2*idx].min_pos;
} else {
tree[idx].min_val = tree[2*idx+1].min_val;
tree[idx].min_pos = tree[2*idx+1].min_pos;
}
}
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
build(1, 1, n);
Node res = query(1, 1, n, 2, 4);
cout << "Min value: " << res.min_val << ", min position: " << res.min_pos << endl;
update(1, 1, n, 3, -1);
res = query(1, 1, n, 2, 4);
cout << "Min value: " << res.min_val << ", min position: " << res.min_pos << endl;
return 0;
}
``