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。