Problem
有一排樹,每個樹分別有 type
和 height
,現在要將其分團,
- 每一團內不允許有相同的
type
- 每一團的花費是最高的
height
計算總花費最小為何?
Sample Input
|
|
Sample Output
|
|
Solution
藉由掃描線的思路,可以得知每一個樹的位置 i
,往左延伸最大多少內不會有重複的 type
。詳見 12890 - Easy Peasy 的技巧。
因此會得到公式$dp([i]) = min(dp[j - 1] + max(height[k])), j \geq f(i), j \le k \le i$
dp[i]
:將前 i 個樹分團的最少費用。
計算這個公式需要 O(n^2)
,由於 n 很大,必須找一個優化將其降下來。
首先知道 f(i)
是非遞減函數 (會一直增加),單純看 i 時,dp[j - 1]
是固定的,但max(height[k])
會逐漸增加,如果能在 O(log n)
時間進行更新、詢問,複雜度將可以降至 O(n log n)
。
每個元素有兩個屬性 (a, b)
query(f(i), i)
:return min(A[k].a + A[k].b), f(i) <= k <= i
update(f(i), i, height[i])
:A[k].b = max(A[k].b, height[i])
左思右想仍然沒有辦法用線段樹完成它,至少是一個很 tricky 的花費計算。
有一個貪心的思路,考慮區間內的計算時,只需要找到嚴格遞減的高度進行更新即可,並非所有的可能進行嘗試。用一個單調隊列,只記錄 [f(i), i]
之間的嚴格遞減的高度資訊,接著每次需要窮舉單調隊列內的所有元素。
複雜度最慘還是 O(n^2)
,隨機測資下速度是快非常多的。
|
|