Leetcode 3161. Block Placement Queries

LeetCode3161:BlockPlacementQueries-利用SegmentTree解决动态区间最大值问题

1. 解题思路

这一题没有搞定,后来是看了答案才多少有了些思路的,感觉人生真的是玄学拉满,每次我休息一整天完全没有学习的时候,哪怕只是出于某些理由被动休息的时候,第二天都会很倒霉,早上起来曼城居然翻车输给曼联了,然后这周的两道hard的题目都没能自力搞定,尤其是后面周赛399的第四题,看了答案都有点云里雾里,简直了……

算了,不发牢骚了,言归正传,这道题思路上的话用的是segment tree(这部分内容可以参阅我之前写的博客:经典算法:Segment Tree),这一点我其实也想到了,因为是需要不断地求0到某一个区间x之间的间隔空间的最大值,这个问题非常适合segment tree的结构,但是这里的问题在于,每插入一块挡板的时候,前后两块挡板之间所有位置上其对应的间隔都会发生变化,因此要改变value的值就不是一个,而是一整个subarray,这会导致算法复杂度过高,我基本就是卡死在了这个地方。

而看了一下大佬们的解答,发现其它部分的思路和我一模一样,但是最核心的区别在于,segment tree当中虽然同样是按照每一个位置进行维护其所在的区间的大小的,但是他只记录了有挡板位置的前侧区间的大小,对于没有放置挡板的位置,虽然它的所处区间的大小也发生了变化,但是必然不会是最大的值,因此没有必要去维护这个位置上的值了。

由此,大佬们就极大地缩减了题目的算法复杂度,使之通过所有的测试样例了。

委实有点精妙了……

2. 代码实现

给出我自己仿写的python代码实现如下:

class SegmentTree:
    def __init__(self, arr):
        self.length = len(arr)
        self.tree = self.build(arr)

    def feature_func(self, *args):
        return max(args)

    def build(self, arr):
        n = len(arr)
        tree = [0 for _ in range(2*n)]
        for i in range(n):
            tree[i+n] = arr[i]
        for i in range(n-1, 0, -1):
            tree[i] = self.feature_func(tree[i<<1], tree[(i<<1) | 1])
        return tree

    def update(self, idx, val):
        idx = idx + self.length
        self.tree[idx] = val
        while idx > 1:
            self.tree[idx>>1] = self.feature_func(self.tree[idx], self.tree[idx ^ 1])
            idx = idx>>1
        return

    def query(self, lb, rb):
        lb += self.length 
        rb += self.length
        nodes = []
        while lb < rb:
            if lb & 1 == 1:
                nodes.append(self.tree[lb])
                lb += 1
            if rb & 1 == 0:
                nodes.append(self.tree[rb])
                rb -= 1
            lb = lb >> 1
            rb = rb >> 1
        if lb == rb:
            nodes.append(self.tree[rb])
        return self.feature_func(*nodes)
    
    
class Solution:
    def getResults(self, queries: List[List[int]]) -> List[bool]:
        n = max(q[1] for q in queries)
        segment_tree = SegmentTree([0 for _ in range(n+1)])
        obstacles = [0]
        
        ans = []
        for query in queries:
            if query[0] == 1:
                x = query[1]
                idx = bisect.bisect_left(obstacles, x)
                prev = obstacles[idx-1]
                segment_tree.update(x, x-prev)
                if idx < len(obstacles):
                    nxt = obstacles[idx]
                    segment_tree.update(nxt, nxt-x)
                bisect.insort(obstacles, x)
            else:
                x, sz = query[1:]
                idx = bisect.bisect_right(obstacles, x)
                prev = obstacles[idx-1]
                _max = max(x-prev, segment_tree.query(0, prev))
                ans.append(sz <= _max)
        return ans

提交代码评测得到:耗时5706ms,占用内存87MB。

### 如何在 VSCode 中安装和配置 LeetCode 插件以及 Node.js 运行环境 #### 安装 LeetCode 插件 在 VSCode 的扩展市场中搜索 `leetcode`,找到官方提供的插件并点击 **Install** 按钮进行安装[^1]。如果已经安装过该插件,则无需重复操作。 #### 下载与安装 Node.js 由于 LeetCode 插件依赖于 Node.js 环境,因此需要下载并安装 Node.js。访问官方网站 https://nodejs.org/en/ 并选择适合当前系统的版本(推荐使用 LTS 版本)。按照向导完成安装流程后,需确认 Node.js 是否成功安装到系统环境中[^2]。 可以通过命令行运行以下代码来验证: ```bash node -v npm -v ``` 上述命令应返回对应的 Node.js 和 npm 的版本号。如果没有正常返回版本信息,则可能未正确配置环境变量。 #### 解决环境路径问题 即使完成了 Node.js 的安装,仍可能出现类似 “LeetCode extension needs Node.js installed in environment path” 或者 “command ‘leetcode.toggleLeetCodeCn’ not found” 的错误提示[^3]。这通常是因为 VSCode 未能识别全局的 Node.js 路径或者本地安装的 nvm 默认版本未被正确加载[^4]。 解决方法如下: 1. 手动指定 Node.js 可执行文件的位置 在 VSCode 设置界面中输入关键词 `leetcode`,定位至选项 **Node Path**,将其值设为实际的 Node.js 安装目录下的 `node.exe` 文件位置。例如:`C:\Program Files\nodejs\node.exe`。 2. 使用 NVM 用户管理工具调整默认版本 如果通过 nvm 工具切换了不同的 Node.js 版本,请确保设置了默认使用的版本号。可通过以下指令实现: ```bash nvm alias default <version> ``` 重新启动 VSCode 后测试功能键是否恢复正常工作状态。 --- #### 配置常用刷题语言 最后一步是在 VSCode 设置面板中的 LeetCode 插件部分定义个人习惯采用的主要编程语言作为默认提交方式之一。这样可以减少频繁修改编码风格的时间成本。 --- ### 总结 综上所述,要在 VSCode 上顺利启用 LeetCode 插件及其关联服务,除了基本插件本身外还需额外准备支持性的后台框架——即 Node.js 应用程序引擎;同时针对特定场景下产生的兼容性障碍采取针对性措施加以修正即可达成目标[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值