📅  最后修改于: 2023-12-03 15:12:42.766000             🧑  作者: Mango
这是 GATE-CS-2015(套装2)第 65 题。本题考查了程序员对数据结构的理解和运用。以下是本题的详细信息和解答。
有一个数列 a1, a2, ..., an。你需要设计一种数据结构和两种操作:
显然,本题是一道查询和修改综合的题目,考虑利用一棵数据结构维护数列。由于我们需要查询区间第 k 大的数,可以考虑利用堆实现。
我们考虑建立一棵以值为关键字的最大堆。在查询操作时,我们先向堆中插入数列 a 中的前 k-1 个元素,然后向后逐一插入 a[k], a[k+1] ...... a[l]。每插入一个数,我们取出堆顶元素,判断它是否在区间[k,l]中,如果在,那么它就是区间[k,l]中第 k 大的数。
修改操作比较简单,我们只需要找到位置i所对应的元素,并将其改为新的值。然后,我们需要重新调整堆以保持堆的性质。
由于查询操作要遍历区间,插入操作要插入 n 个元素,每次插入需要 $O(\log n)$ 的时间复杂度。因此,本题总的时间复杂度为 $O(q \log n)$。
import heapq
class Query(object):
def __init__(self, k, l):
self.k = k
self.l = l
def __cmp__(self, other):
return self.k - other.k
class QueryHeap(object):
def __init__(self):
self.heap = []
self.index_map = {}
def add_query(self, query):
index = len(self.heap)
self.heap.append(query)
self.index_map[query] = index
self.bubble_up(index)
def update_query(self, query, new_k):
index = self.index_map[query]
query.k = new_k
self.bubble_up(index)
def pop(self):
last_query = self.heap.pop()
if self.heap:
query = self.heap[0]
self.heap[0] = last_query
self.index_map[last_query] = 0
self.sink_down(0)
else:
query = last_query
del self.index_map[query]
return query
def bubble_up(self, index):
while index > 0:
parent_index = (index - 1) // 2
if self.heap[parent_index] < self.heap[index]:
self.swap(index, parent_index)
index = parent_index
else:
break
def sink_down(self, index):
end_index = len(self.heap)
while True:
left_child_index = 2*index + 1
right_child_index = 2*index + 2
child_index = None
if left_child_index < end_index:
child_index = left_child_index
if right_child_index < end_index and self.heap[right_child_index] < self.heap[left_child_index]:
child_index = right_child_index
if child_index is not None and self.heap[child_index] > self.heap[index]:
self.swap(index, child_index)
index = child_index
else:
break
def swap(self, index1, index2):
query1 = self.heap[index1]
query2 = self.heap[index2]
self.heap[index1], self.heap[index2] = query2, query1
self.index_map[query1], self.index_map[query2] = index2, index1
class Interval(object):
def __init__(self, left, right):
self.left = left
self.right = right
def __cmp__(self, other):
return self.left - other.left
class IntervalTree(object):
def __init__(self, intervals):
self.root = self.build_tree(intervals)
def build_tree(self, intervals):
if not intervals:
return None
intervals = sorted(intervals)
mid_index = len(intervals) // 2
mid_value = intervals[mid_index]
left_child = self.build_tree(intervals[:mid_index])
right_child = self.build_tree(intervals[mid_index+1:])
node = TreeNode(mid_value, left_child, right_child)
if left_child:
left_child.parent = node
if right_child:
right_child.parent = node
return node
def query(self, k, l):
heap = QueryHeap()
node = self.root
while node:
if node.value.left <= l:
if node.value.right >= k:
if node.left_child:
heap.add_query(Query(k, node.value.right))
if node.right_child:
heap.add_query(Query(node.value.left, l))
break
elif node.value.right < k:
node = node.right_child
else:
node = node.left_child
result = None
for _ in range(k):
query = heap.pop()
result = query.k
if _ == k - 1:
break
if query.l >= l:
if query.k + 1<= result:
break
heap.add_query(Query(result + 1, query.l))
if query.k + 1 == heap.heap[0].k:
break
return result
def update(self, index, new_value):
node = self.root
while node:
if node.value.left <= index <= node.value.right:
node.value = Interval(index, index)
node.update_max_leaf()
break
elif index < node.value.left:
node = node.left_child
else:
node = node.right_child
def build_interval_tree(n):
intervals = [Interval(i + 1, i + 1) for i in range(n)]
return IntervalTree(intervals)
class TreeNode(object):
def __init__(self, value, left_child, right_child):
self.value = value
self.left_child = left_child
self.right_child = right_child
self.parent = None
self.max_leaf = self.value.right
if self.left_child:
self.max_leaf = max(self.max_leaf, self.left_child.max_leaf)
self.left_child.parent = self
if self.right_child:
self.max_leaf = max(self.max_leaf, self.right_child.max_leaf)
self.right_child.parent = self
def update_max_leaf(self):
node = self.parent
while node:
node.max_leaf = max(node.left_child.max_leaf, node.right_child.max_leaf)
node = node.parent
def test():
n = 5
a = [0, 3, 4, 2, 1]
q = [
(1, 3, 2),
(2, 2, 3),
(1, 2, 4),
(2, 4, 4)
]
tree = build_interval_tree(n)
for i in range(n):
tree.update(i+1, a[i])
for op in q:
if op[0] == 1:
result = tree.query(op[1], op[2])
print('Query [{}-{}]: {}'.format(op[1], op[2], result))
else:
index, new_value = op[1], op[2]
tree.update(index, new_value)
new_result = tree.query(2, 4)
print('After update [{}]: Query [2-4]: {}'.format(index, new_result))
test()
以上是本题的解答,欢迎阅读。