weekly contest 457。

題目

https://leetcode.com/problems/power-grid-maintenance/description/

解法

若干個發電廠,某些透過纜線連接在一起。 有兩種操作:

  • 查詢發電廠 x,按照描述回答
  • 關閉發電廠 x

被查詢電廠 x 要由連通的未關閉編號最小的電廠回答。
這是連通塊問題,直覺想到併查集

先按照併查集連接電廠,然後按照所屬連通塊分組。
分組後,每組的電廠編號正好是由大到小。


但是電廠關閉順序不定,可以用 sorted list 維護。
注意:題目沒有保證 x 不會重複關閉,小心檢查。

另一個思路是:我們只在乎當前最小的電廠是否關閉。
每次關閉電廠只先做標記,等到回答詢問時才檢查,若編號最小的電廠被標記則不斷刪除。這叫做懶刪除

時間複雜度 O(c log c + Q)。
空間複雜度 O(c log c)。

class Solution:
    def processQueries(self, c: int, connections: List[List[int]], queries: List[List[int]]) -> List[int]:
        uf = UnionFind(c+1)
        for a, b in connections:
            uf.union(a, b)

        groups = defaultdict(deque)
        for i in range(1, c+1):
            groups[uf.find(i)].append(i)

        online = [True] * (c+1)
        ans = []
        for q_type, x in queries:
            if q_type == 2:
                online[x] = False
                continue

            if online[x]:
                ans.append(x)
                continue

            g = uf.find(x)
            q = groups[g]
            while q and not online[q[0]]:
                q.popleft()

            if q:
                ans.append(q[0])
            else:
                ans.append(-1)

        return ans


class UnionFind:
    def __init__(self, n):
        self.parent = [0] * n
        self.component_cnt = n  # 連通塊數量
        for i in range(n):
            self.parent[i] = i

    def union(self, x, y):
        px = self.find(x)
        py = self.find(y)
        if px != py:
            self.parent[px] = py
            self.component_cnt -= 1  # 連通塊減少 1

    def find(self, x):
        if x != self.parent[x]:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]