BZOJ 1911 特別行動隊 (斜率優化)

2022-04-28 19:30:13 字數 1445 閱讀 3247

感覺這道題目還是比較常規的,首先我們很容易想到dp,因為題目裡面說了選出的人都是連續的,這意味著我們可以從前往後dp。我們直接設 \(f[i]\) 表示前 \(i\) 在分組之後的戰鬥力之和(因為題目沒有明確要求分幾組,所以我們省去這一維度)。然後轉移也比較常規,我們列舉前面的某乙個人 \(k\) 作為這一組人的左端點(右端點就是第 \(i\) 個人)。這題資料範圍很大,我們也不用著急,現將式子列出來,如果轉移不能優化再另尋他法。(事實上這種沒有性質的dp,優化只能靠轉移方程)

轉移方程:

$ f[i]=f[k]+a\times (s[i]-s[k])^2+b\times(s[i]-s[k])+c $

把這個式子拆開你就會看到乙個與 \(i,k\) 都有關的乘積項,這是斜率優化的標誌:

$ f[i] = f[k] + a\times s[i]^2 - 2a\times s[i]\times s[k] + a\times s[k]^2+b\times s[i] - b\times s[k] + c $

然後我們將同一類的項移動到一起,化為斜率優化的標準式:

$ f[k] + a\times s[k]^2 - b\times s[k] = + 2a\times s[i]\times s[k] + f[i] -a\times s[i]^2 - b\times s[i] - c $

然後我們將 乘積項\(2a\times s[i]\times s[k]\) 裡面有關於 \(k\) 的 \(s[k]\) 作為橫座標(自變數) ,然後等式右邊有關 \(k\) 的項 \(f[k] + a\times s[k]^2 - b\times s[k]\) 作為縱座標(應變數)。然後我們要 \(f[i]\) 最大,其實就是讓截距 \(f[i] -a\times s[i]^2 - b\times s[i] - c\) 最大。於是直接斜率優化即可。

#include#include#include#include#include#include#include#include#include#include#include#include#define ll long long

#define db double

#define rg register int

using namespace std;

int n;

ll a,b,c;

int s[1000005];

int q[1000005];

ll g[1000005];

ll f[1000005];

inline int qr()

int main()printf("%lld\n",f[n]);

return 0;

}

BZOJ1911 特別行動隊

目錄題目傳送門 典型的斜率優化 dp 首先如果我們記 sum i 表示前 i 個士兵的戰鬥力之和,那麼我們比較容易的可以得出 o n 2 的 dp f i max f j a sum i sum j 2 b sum i sum j c 如果 k j 並且 k 比 j 更優,那麼可以得出 frac l...

bzoj 1911 特別行動隊

題意 將 n 個人分組,分組後,乙個組的戰鬥力等於 a sum sum b sum c,怎麼分組使得戰鬥力和最大。分析 第一次自己從頭到尾推出來的斜率dp。狀態定義 d i 前 i 個人分組得到的最優值。狀態轉移 d i max d j a sum i sum j 2 b sum i sum j c...

bzoj1911 特別行動隊 斜率優化dp

ac通道 題解 首先很容易想到用字首和,下面的sum表示字首和。然後寫出狀態轉移方程 f i max 假設j比k更優,得到斜率表示式 f j a sum j 2 b sum j f k a sum k 2 b sum k sum j sum k 2a sum i 然後斜率優化走起。include i...