LC 100314. 物块放置查询
https://leetcode.cn/problems/block-placement-queries/description/
线段树 + 辅助的二叉树。表示上应该要选择有固定值的端点,这里默认就是0. 如果以右边为固定端点的话,更新会特别麻烦。
我看到题解里面还有一个做法是使用逆序来回答所有的提问,这样每个安装障碍物可以变为拆除障碍物。好处是可以使用前缀树,实现起来会更简单一些。
另外这里还需要有个辅助二叉树,它的作用是记录某个点之和之后的障碍物,这样可以更新区间。二叉树最好设置哨兵,这样可以简化许多操作:
- `bisect_left(x) - 1` 可以得到比x小的最大数下标
- `bisect_right(x)` 可以得到比x大的最小数下标
前提是要存在这样的数,所以有了哨兵逻辑会简化很多。
class Solution:
def getResults(self, queries: List[List[int]]) -> List[bool]:
maxsz = max([q[1] for q in queries])
n = maxsz + 2
t = 0
while (1 << t) < n:
t += 1
n = 1 << t
INF = 1 << 30
trees = [0] * (2 * n)
def update_once(p):
l, r = 2 * p, 2 * p + 1
trees[p] = max(trees[l], trees[r])
def update(p, v):
p += n
trees[p] = v
p = p // 2
while p:
update_once(p)
p = p // 2
def query(p, s, e, end):
if e <= end: return trees[p]
m = (s + e) // 2
if end <= m:
return query(2 * p, s, m, end)
a = trees[2 * p]
b = query(2 * p + 1, m + 1, e, end)
return max(a, b)
ans = []
from sortedcontainers import SortedList
sl = SortedList([0, maxsz + 1])
for q in queries:
x = q[1]
idx = sl.bisect_left(x)
pre = sl[idx - 1]
if q[0] == 1:
nxt = sl[idx]
update(x, x - pre)
update(nxt, nxt - x)
sl.add(x)
else:
r = query(1, 0, n - 1, pre)
r = max(r, x - pre)
# print(r)
ans.append(r >= q[2])
return ans