[leetcode brush question] 2659. Clear the array (first experience of tree array)

Question screenshot

insert image description here
insert image description here

topic analysis

  • Direct simulation is square complexity, which will exceed time complexity
  • We delete the smallest one, and then we need to delete the next smallest one. How to find the distance between them?
  • Perhaps some of the intervals were deleted again? How to record the rest?
  • We record through the tree array, query(i, j) indicates how many elements in [i, j] have been deleted
  • Therefore, we need to break down one by one, first look at the current position idx of the element that needs to be placed in the first position, assuming that the original position of the first element before is pre
  • If pre < idx: it is easy to move directly from pre to idx, ans += idx - pre - query(pre, idx)
  • Conversely, you need to move to n first, and then move from 1 to idx: ans += (n - pre - query(pre, n)) + (idx - query(1, idx))
  • Finally, add n deletes ans += n
  • In fact, we need to maintain an array of 1,2,3,...,n virtually in our mind

ac code

# 树状数组模板
class BIT:
    def __init__(self, n):
        self.tree = [0] * n

    # 将下标 i 上的数加一
    def inc(self, i: int) -> None:
        while i < len(self.tree):
            self.tree[i] += 1
            i += i & -i # add lowbit to right father 

    # 返回闭区间 [1, i] 的元素和
    def sum(self, i: int) -> int:
        res = 0
        while i > 0:
            res += self.tree[i]
            # i &= i - 1
            i -= i & -i # minus lowbit to left father
        return res

    # 返回闭区间 [left, right] 的元素和
    def query(self, left: int, right: int) -> int:
        return self.sum(right) - self.sum(left - 1)



class Solution:
    def countOperationsToEmptyArray(self, nums: List[int]) -> int:
        n = len(nums)
        ans = n
        t = BIT(n + 1)
        pre = 1
        # 把数组先转成1到n
        # 然后再得到最后希望的位置
        # new_nums[0]表示最后排在第0个位置的应该是new_nums[0]
        new_nums = sorted(range(n), key = lambda x: nums[x])
        for k, idx in enumerate(new_nums):
            print(k, idx)
            idx += 1
            # pre现在位于第一位,现在希望idx位于第一位
            if pre <= idx:
                ans += idx - pre - t.query(pre, idx) # query得到的是中间删除的个数
            else:
                ans += (n - pre - t.query(pre, n)) + (idx - t.query(1, idx))
            t.inc(idx)
            pre = idx
        return ans

Tree array template

# 树状数组模板
class BIT:
    def __init__(self, n):
        self.tree = [0] * n

    # 将下标 i 上的数加一
    def inc(self, i: int) -> None:
        while i < len(self.tree):
            self.tree[i] += 1
            i += i & -i # add lowbit to right father 

    # 返回闭区间 [1, i] 的元素和
    def sum(self, i: int) -> int:
        res = 0
        while i > 0:
            res += self.tree[i]
            # i &= i - 1
            i -= i & -i # minus lowbit to left father
        return res

    # 返回闭区间 [left, right] 的元素和
    def query(self, left: int, right: int) -> int:
        return self.sum(right) - self.sum(left - 1)

tree array

It is a binary-based data structure that can perform efficient 1. single-point modification, single-point query, 2. range modification, single-point query, 3. range query, range modification

insert image description here
Here we need to define a concept of lowbit, that is, the new binary consisting of the lowest bit 1 and 0 of the current binary:
fa = child + lowbit(child) This is a key property

  • For modification: after adding the current node directly, just add the fa node
  • For queries: consider the new node child - lowbit(child), and finally add them all up
    insert image description here

Summarize

  • This is a question about subscript arrays
  • After deletion, if the current deleted node and the surviving node tree moved in the previously deleted node are recorded
  • Consider using tree arrays for fast lookups

Guess you like

Origin blog.csdn.net/weixin_40986490/article/details/130507649