线段树与st表在区间最值的效率差异
时间: 2024-06-20 12:02:53 浏览: 12
线段树和ST表都是支持区间最值查询的数据结构。线段树使用树形结构,而ST表则是使用预处理数组的方式来实现。两种数据结构的时间复杂度都可以达到 $O(\log n)$。
对于静态求解问题(即不需要支持修改操作),ST表实现起来比较简单,且常数较小,所以常常比线段树效率更高。但是,线段树有着更好的可扩展性,可以在需要支持动态修改的问题上使用。在这种情况下,由于ST表需要根据区间大小预处理,在区间大小相对较大的情况下,ST表会出现一定的效率劣势。而线段树不需要预处理,可以在任何情况下都保持较好的效率。
因此,我们可以总结出以下结论:
- 当问题是静态求解,且没有修改操作时,ST表通常比线段树效率更高。
- 当问题需要支持动态修改操作时,或者区间大小较大时,线段树通常是更好的选择。
相关问题
用线段树算区间最值代码
以下是一个用线段树算区间最值的示例代码,以查询区间最小值为例:
```cpp
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 100005;
int n, m;
int a[MAXN];
struct Node {
int l, r, minn;
} tr[MAXN*4];
// 建立线段树
void build(int u, int l, int r) {
tr[u].l = l, tr[u].r = r;
if (l == r) { // 叶子节点
tr[u].minn = a[l];
return;
}
int mid = (l + r) >> 1;
build(u<<1, l, mid);
build(u<<1|1, mid+1, r);
tr[u].minn = min(tr[u<<1].minn, tr[u<<1|1].minn);
}
// 查询区间最小值
int query(int u, int ql, int qr) {
if (ql <= tr[u].l && tr[u].r <= qr) { // 完全包含
return tr[u].minn;
}
int mid = (tr[u].l + tr[u].r) >> 1;
int res = 0x3f3f3f3f; // 初始化为一个极大值
if (ql <= mid) res = min(res, query(u<<1, ql, qr)); // 左子区间有交集
if (qr > mid) res = min(res, query(u<<1|1, ql, qr)); // 右子区间有交集
return res;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
build(1, 1, n); // 建立线段树
while (m--) {
int l, r;
scanf("%d%d", &l, &r);
printf("%d\n", query(1, l, r));
}
return 0;
}
```
这段代码中,建立线段树的过程采用递归方式实现,查询区间最小值的过程也采用递归方式实现。对于每个节点,维护该节点对应区间的最小值。查询区间最小值的过程,采用线段树的递归查询方式,将查询区间划分成若干个离散的单元,并依次查询每个单元,最终得到查询区间的最小值。
线段树的区间求和与区间修改
线段树是一种二叉树形数据结构,适用于动态的区间查询和区间修改。下面给出线段树的区间求和和区间修改的实现方法。
1.区间求和
线段树的区间求和操作可以用递归的方式进行。对于每一个非叶节点,维护一个区间的和,左右儿子分别维护左半区间和右半区间的和。查询区间的时候,用二分的方式进行递归,直到查询的区间和当前节点所维护的区间有交集为止,将左右儿子的和相加即可得到查询区间的和。
2.区间修改
线段树的区间修改可以用懒标记的方式来实现。对于每一个节点,维护一个懒标记,表示这个节点的区间是否被修改过。在对一个区间进行修改时,将懒标记打上,然后递归下去更新左右儿子的区间和,最后将懒标记清空。查询的时候,如果一个节点的懒标记不为空,就先下推懒标记,再递归查询子区间。
参考代码:
区间求和:
```python
class SegmentTree:
def __init__(self, n):
self.n = n
self.tree = * (n*4)
def build(self, node, left, right, nums):
if left == right:
self.tree[node] = nums[left]
return
mid = (left + right) >> 1
self.build(node*2, left, mid, nums)
self.build(node*2+1, mid+1, right, nums)
self.tree[node] = self.tree[node*2] + self.tree[node*2+1]
def query(self, node, left, right, qleft, qright):
if left > qright or right < qleft:
return 0
if left >= qleft and right <= qright:
return self.tree[node]
mid = (left + right) >> 1
return self.query(node*2, left, mid, qleft, qright) + self.query(node*2+1, mid+1, right, qleft, qright)
def update(self, node, left, right, uleft, uright, val):
if left > uright or right < uleft:
return
if left >= uleft and right <= uright:
self.tree[node] += val * (right - left + 1)
if left != right:
self.lazy[node*2] += val
self.lazy[node*2+1] += val
return
mid = (left + right) >> 1
self.update(node*2, left, mid, uleft, uright, val)
self.update(node*2+1, mid+1, right, uleft, uright, val)
self.tree[node] = self.tree[node*2] + self.tree[node*2+1]
```
区间修改:
```python
class SegmentTree:
def __init__(self, n):
self.n = n
self.tree = * (n*4)
self.lazy = * (n*4)
def build(self, node, left, right, nums):
if left == right:
self.tree[node] = nums[left]
return
mid = (left + right) >> 1
self.build(node*2, left, mid, nums)
self.build(node*2+1, mid+1, right, nums)
self.tree[node] = self.tree[node*2] + self.tree[node*2+1]
def query(self, node, left, right, qleft, qright):
if left > qright or right < qleft:
return 0
if left >= qleft and right <= qright:
return self.tree[node]
mid = (left + right) >> 1
self.pushdown(node, mid-left+1, right-mid)
return self.query(node*2, left, mid, qleft, qright) + self.query(node*2+1, mid+1, right, qleft, qright)
def update(self, node, left, right, uleft, uright, val):
if left > uright or right < uleft:
return
if left >= uleft and right <= uright:
self.tree[node] += val * (right - left + 1)
if left != right:
self.lazy[node*2] += val
self.lazy[node*2+1] += val
return
mid = (left + right) >> 1
self.pushdown(node, mid-left+1, right-mid)
self.update(node*2, left, mid, uleft, uright, val)
self.update(node*2+1, mid+1, right, uleft, uright, val)
self.tree[node] = self.tree[node*2] + self.tree[node*2+1]
def pushdown(self, node, leftlen, rightlen):
if self.lazy[node]:
self.tree[node*2] += self.lazy[node] * leftlen
self.tree[node*2+1] += self.lazy[node] * rightlen
self.lazy[node*2] += self.lazy[node]
self.lazy[node*2+1] += self.lazy[node]
self.lazy[node] = 0
```