AtCoder 🟢 ABC436F Starry Landscape Photo
題目的難度顏色使用 Luogu 上的分級,由簡單到困難分別為 🔴🟠🟡🟢🔵🟣⚫。
🔗 ABC436F Starry Landscape Photo
Problem Statement
題目簡述
夜空中有 顆星星排成一列,第 顆星星(從東邊數起,1-indexed)的亮度排名為 (,且 為排列)。
拍照時需選擇一個連續區間 和一個亮度閾值 ,照片會包含該區間內所有亮度排名 的星星(即最亮的 顆星範圍內)。
求能拍出的不同星星集合的數量(空集合除外)。
具體描述
透過指定 組合,可以得到一個星星集合。
求在所有可能的 組合中,所能得到的不同星星集合數量。
Constraints
約束條件
- 是 的一個排列。
思路:枚舉集合的最大值中心
解題思路
這道題的核心在於如何不重不漏地計算每一個可能的星星集合。
由於集合是由「最大亮度排名 」截斷產生的,對於任意一個符合條件的集合,其中 值最大的那顆星星是唯一的。我們可以利用這個性質,將每個集合唯一映射到其「 值最大的元素」上進行統計。
方法一:按照亮度從小到大枚舉星星,對下標維護 BIT
1. 以「最大亮度星星」為中心
假設某個集合 中 值最大的星星是 (位置 ,亮度 )。
那麼這個集合 必然滿足:
- 。
- 中所有其他元素的亮度都 。
- 是由位置 左右兩側延伸出去的某些「亮度 的星星」所組成的。
具體來說,如果我們只看亮度 的星星,那麼 就是包含 的一個連續段。
因此,問題轉化為:對於每一顆星星(當作最大值中心),在只保留亮度 的星星的情況下,有多少個包含 的連續區間?
2. 利用 BIT 進行計數
我們可以按照亮度 到 的順序枚舉星星:
- 當處理亮度為 的星星(位置 )時,我們希望知道在它左邊和右邊分別有多少個位置 滿足 。
- 利用 Fenwick Tree (BIT) 維護位置資訊。每處理一個亮度 ,就將其位置 加入 BIT。
- 查詢:
- : 左側(含 )已加入 BIT 的星星數量。
- : 右側(含 )已加入 BIT 的星星數量。
- 根據乘法原理,以該星星為最大值的合法集合數為 。這相當於在左側可選的範圍中選一個起點,在右側可選的範圍中選一個終點。
結論
總答案即為所有星星作為中心時 的總和。
複雜度分析
- 時間複雜度:。
- 空間複雜度:。
1 | from atcoder.fenwicktree import FenwickTree |
方法二:按照下標順序枚舉星星,對亮度的值域維護 BIT
這個方法雖然遍歷順序不同,但數學意義上完全等價,依然是計算「以當前星星為最大值」的集合數量。
1. 調整維護的對象
我們按照位置順序 遍歷星星。
- 對於當前星星 ,其亮度為 。
- 左邊比我小的數量 ():
- 使用 BIT 維護「目前已遍歷過的星星的亮度分佈」。
- 查詢
bit.sum(0, b)即為 左側亮度 的星星數量。 - 加上自己,則 。
- 右邊比我小的數量 ():
- 這裡利用了一個巧妙的性質:整個陣列中,亮度 的星星總共有 顆(因為 是 的排列)。
- 其中有 顆已經在左側出現過了。
- 因此,剩下的必定在右側。
- 。
透過這種方式,我們省去了對右側的顯式查詢,僅需一次遍歷與一個維護值域的 BIT。
複雜度分析
- 時間複雜度:。
- 空間複雜度:。
1 | from atcoder.fenwicktree import FenwickTree |
兩種寫法的比較
雖然兩者最終計算的公式皆為 ,但在實作視角上有顯著差異。
| 特徵 | 方法一 | 方法二 |
|---|---|---|
| 遍歷順序 | 按亮度 () | 按位置 () |
| BIT 維護內容 | 維護位置的出現情況 | 維護亮度的出現情況 |
| BIT 查詢意義 | query(0, pos): 查位置區間和 |
query(0, val): 查值域區間和 |
| 計算 | 直接查 BIT (因為 BIT 裡只有比我小的星) | 查 BIT (統計目前遍歷過且比我小的) |
| 計算 | 直接查 BIT | 利用全域性質推算:總共比我小的 - 左邊比我小的 |
優劣分析:
- 方法二 更優雅:
- 不需要預處理
pos陣列(不需反查亮度對應的位置)。 - 只需要一次遍歷輸入陣列 。
- 充分利用了「排列」的性質 (比 小的有 個) 來推算右側數量。
- 不需要預處理
- 方法一 更直觀:
- 「按亮度從小到大加入」是處理數值限制問題的經典技巧(類似 Kruskal 或離線查詢)。
- 思路線性單純:先把小的放進去,查詢時場上存在的都是合法的。
寫在最後
PROMPT
本部落格所有文章除特別聲明外,均採用CC BY-NC-SA 4.0 授權協議。轉載請註明來源 十六個天亮!
評論
WalineGiscus







