24/03/20 貪心(一)

2huk發表於2024-03-20

(1) CF1684D Traps

\(n\) 個數字 \(a_1 \sim a_n\) 排成一排,你需要從左到右依次越過所有數。

兩種越過 \(i\) 的方式:

  1. 花費 \(a_i\) 的代價越過;
  2. 花費 \(0\) 的代價越過,後面的 \(a_i\) 都加 \(1\)

現在你擁有最多 \(k\) 次操作二的機會,求最小的代價總和。


一定會使用 \(k\) 次操作二。否則可以在最後一個使用操作一的位置改用操作二,使答案更優。

假設這 \(k\) 次操作二的地方為 \(i_1, i_2, \dots, i_k\),我們考慮其中一個位置 \(i_j\) 的收益(收益指在 \(i_j\) 位置由操作一改為操作二後答案會變小多少):

  • 本身的代價 \(a_{i_j}\) 變成了 \(0\),收益增加 \(a_{i_j}\)
  • 位置 \(i_j + 1 \sim n\) 中,除了位置 \(i_{j + 1}, i_{j + 2}, \dots, i_{k}\),代價都會加一(因為它們在跳躍時代價都是 \(0\)),收益減少 \(n - i_j - (k - j)\)

綜上,總收益為:

\[\sum_{j=1}^k (a_{i_j} - n + i_j + k - j) \]

整理得:

\[-nk + k^2 - \frac{k(k+1)}2 + \sum_{j=1}^k(a_{i_j} + i_j) \]

顯然我們希望讓收益越大越好,所以我們得目標是最大化這個式子的值。

其中 \(-nk + k^2 - \frac{k(k+1)}2\) 為定值,我們希望最大化 \(\sum_{j=1}^k(a_{i_j} + i_j)\)。所以我們將所有值按照 \(a_i + i\) 排序並取前 \(k\) 大即可。

(2) CF1029E Tree with Small Distances

給定一顆 \(n\) 個節點的樹,以 \(1\) 為根。

求最少在樹中加幾條邊,使得任意一點到 \(1\) 的距離均小於等於 \(2\)


不難發現最優策略中,每條加的邊都有端點 \(1\)

第一步,最自然的想法就是將 \(1\)最深的葉節點連邊。其實不然,最優的策略是連線 \(1\) 和葉子節點的父親。這樣能把這個葉子節點的所有兄弟和它父親的父親都管控到。

接下來上一步的點就不需要考慮了。我們要做的仍然是連線 \(1\) 和最深的點的父親。如此迭代即可。

實現上,我們可以維護大根堆,以節點的深度從大到小排序。每次取出堆頂即可。

(3) CF1197C Array Splitting

給出一個長度為 \(n\) 的嚴格單調增的序列,將其分成 \(k\) 段,使得每一段的極差的和最小,求這個最小的和。


推式子。

若這 \(k\) 段分別為 \([i_1, i_2 - 1], [i_2, i_3 - 1], \dots, [i_k, i_{k + 1} - 1]\),其中 \(i_1 = 1, i_{k + 1} = n + 1\)。那麼極差和為:

\[a_{i_2 - 1} - a_{i_1} + a_{i_3 - 1} - a_{i_2} + a_{i_4 - 1} - a_{i_3} + \dots + a_{i_{k + 1} - 1} - a_{i_k} \]

整理一下,把 \(+a_{i_j - 1}\)\(-a_{i_j}\) 放在一起:

\[-a_{i_1} + a_{i_{k+1} - 1} + (a_{i_2 - 1} - a_{i_2}) + (a_{i_3 - 1} - a_{i_3}) + \dots + (a_{i_k - 1} - a_{i_k}) \]

其中 \(-a_{i_1} + a_{i_{k+1} - 1}\)\(a_n - a_1\) 是一定的。我們希望讓這個式子的值最小,就意味著我們要最小化 \((a_{i_2 - 1} - a_{i_2}) + (a_{i_3 - 1} - a_{i_3}) + \dots + (a_{i_k - 1} - a_{i_k})\)。因此求 \(d_i = a_{i - 1} - a_i\) 的前 \(k - 1\) 小即可。

(3) CF1038D Slime

給定 \(n\) 個數 \(a_i\)。每次可以選擇兩個相鄰的 \(a_i, a_{i + 1}\) 將其合併為 \(a_i - a_{i + 1}\)\(a_{i + 1} - a_i\)。求 \(n - 1\) 次操作後的數的最大值。


多手玩幾組可以發現,最終的答案一定是對每個 \(a_i\) 乘上 \(\pm 1\) 的係數後求和。因為題目的操作為 \(a_i - a_{i + 1}\)\(a_{i + 1} - a_i\),也就是將相鄰兩個數分別乘上 \(\pm 1\)

所以我們可以對於每個負數乘 \(-1\) 變成正數,正數乘 \(1\) 保持正數,再求和即為答案。其實就是每個數的絕對值之和。

注意會有一個問題。將每個 \(a_i\)\(\pm 1\) 的過程中,不能做到將所有 \(a_i\) 全部乘相同的係數。所以在所有 \(a_i\) 同號時貪心選擇某個數乘另外一個係數即可。

(4) CF804A Find Amir

有一張 \(n\) 個節點的完全圖,其中連線 \(i, j\) 兩點的邊的邊權為 \((i + j) \bmod (n + 1)\)。求走完所有城市所需的最小花費(起點任選)。


方案是 \(1 \to n \to 2 \to (n - 1) \to 3 \to \dots\),邊權分別為 \(0, 1, 0, 1, \dots\)

所以答案為邊數的一半,即 \(\left \lfloor \dfrac {n-1}2 \right \rfloor\)

相關文章