↓快轉到主要內容
  1. LeetCode/

LeetCode 2382: Maximum Segment Sum After Removals

·1 分鐘· ·
LeetCode Hard Union-Find Prefix-Sum Ordered-Set Array
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

基本資料
#

難易度: hard 第一次嘗試:2026-07-26

  • 提交紀錄:Time Limit Exceeded ×2 → Accepted → Wrong Answer → Accepted

解題思路
#

一個一個刪除會把區段切開,但 Union-Find 只能合併。倒著做(Union-Find 的「倒著做」):從全部刪光開始,依相反順序把元素加回去,跟左右已經存在的區段合併。

  • 每個根記它的區段總和 total[root]。
  • 倒著加回去時區段只會變長、總和只會變大(數字都是正的),所以目前最大值用一個變數維護就好。
  • 第 i 次刪除後的答案,就是倒著加回 removeQueries[i] 之前的最大值。

我的嘗試
#

版本問題
兩次 TLE想法對,但每一步都用 max(group_sum.values()) 重算所有區段的最大值,整體 O(n²);第一版的 find 也沒有路徑壓縮
AC改用陣列,最大值用一個變數維護
WA換一個做法:排序好的刪除位置 + 前綴和 + 堆積延遲刪除。但從堆積拿掉時沒有把刪除計數減 1,一個區段被刪,所有同樣總和的區段都跟著被丟掉。例如 nums = [3, 1, 3]、removeQueries = [1, 2, 0]:答案是 [3, 3, 0],這版回傳 [3, 0, 0]
AC補上計數減 1(但 list.insert 是 O(n),跑了 1.3 秒)

正確解法
#

class Solution:
    def maximumSegmentSum(self, nums: List[int], removeQueries: List[int]) -> List[int]:
        n = len(nums)
        parent = list(range(n))
        total = [0] * n
        alive = [False] * n

        def find(x):
            while parent[x] != x:
                parent[x] = parent[parent[x]]
                x = parent[x]
            return x

        res, best = [], 0
        for i in reversed(removeQueries):
            res.append(best)                       # 加回 i 之前的答案
            alive[i] = True
            total[i] = nums[i]
            for j in (i - 1, i + 1):
                if 0 <= j < n and alive[j]:
                    rj, ri = find(j), find(i)
                    parent[rj] = ri
                    total[ri] += total[rj]
            best = max(best, total[find(i)])
        return res[::-1]

複雜度
#

時間 O(n · α(n)),空間 O(n)。

要特別避免的錯誤
#

  • 不要每一步都重算所有集合的最大值。
  • 延遲刪除時,從堆積拿掉一個就要把對應的計數減 1。
  • 記錄答案要在加回之前,而且最後要反轉。

面試口說整理
#

刪除會切開區段,Union-Find 不能拆,所以我倒著把元素加回去,跟左右存在的區段合併,根上記總和。數字都是正的,加回去最大值只會變大,用一個變數維護。每次加回之前的最大值就是那次刪除後的答案,最後反轉。時間 O(n α(n))。

相關文章

LeetCode 2106: Maximum Fruits Harvested After at Most K Steps
·1 分鐘
LeetCode Hard Sliding-Window Prefix-Sum Binary-Search Array
LeetCode 2106 解題筆記:採到的一定是連續一段水果;走完 [L, R] 的最少步數是 (R - L) + min(|start - L|, |R - start|),在水果陣列上用滑動視窗
LeetCode 220: Contains Duplicate III
·2 分鐘
LeetCode Hard Sliding-Window Bucket-Sort Ordered-Set Sorting Array
LeetCode 220 解題筆記:桶大小設成 valueDiff + 1,同一個桶裡的兩個數一定符合;只要再看相鄰兩個桶。視窗只保留最近 indexDiff 個數,所以每個桶最多一個數
LeetCode 2709: Greatest Common Divisor Traversal
·2 分鐘
LeetCode Hard Math Number-Theory Union-Find Sieve Gcd Array
LeetCode 2709 解題筆記:任兩個 index 都能互通 ⇔ 全部在同一個連通塊;用 SPF 分解質因數,數字跟它的質因數在 Union-Find 裡合併;1 要特別處理
LeetCode 952: Largest Component Size by Common Factor
·2 分鐘
LeetCode Hard Math Number-Theory Union-Find Hash-Table Array
LeetCode 952 解題筆記:有共同因數 ⇔ 有共同的質因數;把每個數分解質因數,同一個質因數的 index 用 Union-Find 合併,不用兩兩算 GCD
LeetCode 2302: Count Subarrays With Score Less Than K
·1 分鐘
LeetCode Hard Sliding-Window Prefix-Sum Binary-Search Array
LeetCode 2302 解題筆記:分數 = 總和 × 長度,都是正數,視窗越大分數越大;分數 >= k 就縮左邊,以 right 結尾的合法子陣列有 right - left + 1 個
LeetCode 2968: Apply Operations to Maximize Frequency Score
·1 分鐘
LeetCode Hard Sliding-Window Sorting Prefix-Sum Binary-Search Array
LeetCode 2968 解題筆記:排序後,把一段全部變成同一個值,最省的目標是中位數;用前綴和 O(1) 算花費,花費隨視窗變大而變大,可以滑動