关于如何用线段树实现查找区间内第一个小于(大于)某一值x的方法

目的:用线段树查找一个区间里面第一个小于x的元素

对于这种问题,我们首先可能会想到用集合维护一个单调性然后加一个二分查找,这样做没问题,但是用STL会太慢,用手写的话暂时还不会。

那么如何在没有单调性的时候查找呢,或者说我就是要用线段树呢?
首先有一个粗暴的方法,直接二分,然后调用线段是,时间复杂度(logn)^2,对于大的数据还是不太理想。

那么直接使用线段树可以么?当然是可以的 (不然我就不写这篇博客了)
我们先看线段树的查找方式,最终会被划分成若干个小区间,这些小区间加起来就是最终我们需要的答案,我们可以很轻松地找到我们查找的元素在哪个小区间里面(讨论一下即可)
对于一个小区间,就简单了很多,线段树自己就有二分性质,所以先看左子树可行吗,如果不可行就要右子树,也就自然而然的找到了我们需要的第一个小于x的值,对于小区间左子树是否可行的判断是很快的,直接进入递归然后加上一个判断如果待查找区间已经包含了L~R,那么就直接可以使用minv函数判断是否存在了。

时间复杂度:log2n+log2n(若干个小区间+一次二分),就比那种暴力二分的方法好多啦

这个方法既避免了set,也有更广的应用范围,在单调性分析没那么尽善尽美的情况下,我们依然有一个比较厉害的手段可以实现较复杂的查找,达到正常时间复杂度。

代码示例

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
下面是使用 Python 实现线段查找区间内最大的代码: ```python class SegmentTree: def __init__(self, nums): self.n = len(nums) self.tree = [0] * (self.n * 4) self.build_tree(nums, 0, 0, self.n - 1) def build_tree(self, nums, i, l, r): if l == r: self.tree[i] = nums[l] else: mid = (l + r) // 2 self.build_tree(nums, i * 2 + 1, l, mid) self.build_tree(nums, i * 2 + 2, mid + 1, r) self.tree[i] = max(self.tree[i * 2 + 1], self.tree[i * 2 + 2]) def query(self, i, l, r, ql, qr): if ql <= l and qr >= r: return self.tree[i] elif ql > r or qr < l: return float('-inf') else: mid = (l + r) // 2 left = self.query(i * 2 + 1, l, mid, ql, qr) right = self.query(i * 2 + 2, mid + 1, r, ql, qr) return max(left, right) ``` 其中,SegmentTree 类的构造函数中,build_tree 方法用于构建线段;query 方法用于查询区间内的最大。具体实现如下: 1. build_tree 方法中,i 是当前节点的下标,l 和 r 分别是当前节点所代表的区间的左端点和右端点。如果区间只有一个元素,则将当前节点的设为该元素的;否则,递归构建左右子,并将当前节点的设为左右子中的最大。 2. query 方法中,i、l 和 r 的含义同上,ql 和 qr 分别是查询区间的左端点和右端点。如果当前节点所代表的区间完全包含在查询区间内,则返回当前节点的;如果当前节点所代表的区间完全不在查询区间内,则返回负无穷;否则,递归查询左右子,并返回左右子中的最大。 使用示例: ```python nums = [1, 3, 2, 7, 9, 11] st = SegmentTree(nums) print(st.query(0, 0, st.n - 1, 1, 4)) # 输出:7 ``` 其中,nums 是待构建线段的列表,st 是构建的线段对象,st.query(0, 0, st.n - 1, 1, 4) 表示查询 nums[1:5] 区间内的最大,结果为 7。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值