线段树RMQ

基于线段树RMQ的操作:

在给定数列a0,a1,…,an-1的情况下,可以在O (logn)时间内完成下面操作:

  1. 给定s和t,求区间[s,t)的最小值
  2. 给定i和x,将ai的值改为x

假设给定初始数组 date[8]={6,3,1,9,7,4,8,5}
所得线段树如图:
在这里插入图片描述
实际上,每个节点隐含有对应的区间,这是线段树所必须具备的元素,而其他元素则根据题目而改变,例如,RMQ则为对应区间的最小值。
所以实际上的线段树如图:
在这里插入图片描述


1.RMQ查询

如果要求区间[0,6)的最小值,我们只需查找如下三个节点
在这里插入图片描述
从根节点出发,查询分为三种情况:

  • 当查询区间与节点区间完全无交叉时返回一个infinity值
  • 当查询区间完全包含节点区间时,返回节点的值
  • 当有一部分交叉时,则递归儿子节点

2.更新叶子节点

若用2将7代替,则需要跟新3个节点的值
在这里插入图片描述
此程序直接初始化数组时建树,也可以通过不断更新叶子节点的方式建树


时间复杂度:对于每个深度最多访问常数个节点,因此为O(logn)

#include<iostream>
#include<stdlib.h>
#include<algorithm>
#define MAX 100
#define INF 100000
using namespace std;

int n;
int date[MAX];//存储原始数据
int tree[MAX];//存储线段树

//创建线段树
void init() {
	int count = 2 * n - 2;
	for (int i = n - 1; i <= count; i++)
		tree[i] = date[i - n + 1];
	int p = (count - 1) / 2;
	while (p >= 0) {
		int lch = 2 * p + 1;
		int rch = 2 * p + 2;
		tree[p] = min(tree[lch], tree[rch]);
		p--;
	}
}
//更新叶子节点值,也可以通过不断跟新叶子节点的方式建树
void update(int k,int a) {
	tree[k + n - 1] = a;
	int p = (k + n - 2) / 2;
	while (p > 0) {
		int lch = 2 * p + 1;
		int rch = 2 * p + 2;
		tree[p] = min(tree[lch], tree[rch]);
		p = (p - 1) / 2;
	}
}
//查询RMQ,k为当前节点,[l,r)为当前节点区间,[a,b)为需要查询的区间
int query(int k,int a,int b,int l,int r) {
	//当[a,b)与[l,r)不相交的时候,返回一个较大值
	if (a >= r || b <= l) return INF;
	//当[a,b)完全包含[l,r)时,则返回节点的值
	else if (a<=l&&b>=r) return tree[k];
	//当包含一部分,则递归
	else {
		int mid = (l + r) / 2;
		int lch = query(2 * k + 1, a, b, l, mid);
		int rch = query(2 * k + 2, a, b, mid, r);
		return min(lch, rch);
	}
}
int main() {
	cin >> n;
	for (int i = 0; i < n; i++)
		cin >> date[i];
	init();
	for (int i = 0; i < 2 * n - 1; i++)
		cout << tree[i];
	cout << endl << query(0, 0, 6, 0, 8);
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值