upper = max(instructions)
# 初始化线段树
seg = SegmentTree(upper, 1)
for instruction in instructions:
# 进行两次查询
l = seg.queryCount(1, instruction - 1)
r = seg.queryCount(instruction + 1, upper)
ans = (ans + min(l, r)) % mod
# 进行一次更新
seg.updateCount(instruction)
return ans
代码
代码支持:Python3
Python3 Code:
class SegmentTree:
def __init__(self, upper, lower):
"""
data:传入的数组
"""
self.lower = lower
self.upper = upper
# 申请4倍data长度的空间来存线段树节点
self.tree = [0] * (4 * (upper - lower + 1)) # 索引i的左孩子索引为2i+1,右孩子为2i+2
# 本质就是一个自底向上的更新过程
# 因此可以使用后序遍历,即在函数返回的时候更新父节点。
def update(self, tree_index, l, r, index):
"""
tree_index:某个根节点索引
l, r : 此根节点代表区间的左右边界
index : 更新的值的索引
"""
if l > index or r < index:
return
self.tree[tree_index] += 1
if l == r:
return
mid = (l + r) // 2
left, right = tree_index * 2 + 1, tree_index * 2 + 2
self.update(left, l, mid, index)
self.update(right, mid + 1, r, index)
def updateCount(self, index: int):
self.update(0, self.lower, self.upper, index)
def query(self, tree_index: int, l: int, r: int, ql: int, qr: int) -> int:
"""
递归查询区间[ql,..,qr]的值
tree_index : 某个根节点的索引
l, r : 该节点表示的区间的左右边界
ql, qr: 待查询区间的左右边界
"""
if qr < l or ql > r:
return 0
# l 和 r 在 [ql, qr] 内
if ql <= l and qr >= r:
return self.tree[tree_index]
mid = (l + r) // 2
left, right = tree_index * 2 + 1, tree_index * 2 + 2
return self.query(left, l, mid, ql, qr) + self.query(right, mid + 1, r, ql, qr)
def queryCount(self, ql: int, qr: int) -> int:
"""
返回区间[ql,..,qr]的计数信息
"""
return self.query(0, self.lower, self.upper, ql, qr)
class Solution:
def createSortedArray(self, instructions: List[int]) -> int:
mod = 10 ** 9 + 7
ans = 0
# eg: 1 2 2 3
upper = max(instructions)
seg = SegmentTree(upper, 1)
for instruction in instructions:
l = seg.queryCount(1, instruction - 1)
r = seg.queryCount(instruction + 1, upper)
ans = (ans + min(l, r)) % mod
seg.updateCount(instruction)
return ans