bzoj3156防禦準備 DP之單調佇列優化

2021-08-17 17:16:54 字數 1517 閱讀 1361

第一行為乙個整數n表示戰線的總長度。

第二行n個整數,第i個整數表示在位置i放置守衛塔的花費ai。

output

共乙個整數,表示最小的戰線花費值。

sample input

102 3 1 5 4 5 6 3 1 2

sample output

這道題是dp,這是毋庸置疑的。我們先考慮暴力dp,我們顯然可以推出n²的dp,然後再進行優化。

我們設f[i][0]表示第i點不建守衛塔時,到此地的最小花費,而f[i][1]就表示在i建造守衛塔時到此地的最小花費,則我們可以推出:

f[i][1]=min(f[i+1][1],f[i+1][0])+a[i]

f[i][0]=min(f[i][0],f[j][1]+(j-i+1)*(j-i)/2) //j=i+1~n

//最後ans=min(f[1][0],f[1][1])

//由於若f[i][0]由j推出,則i+1~j-1全由j推出,則增加的值為σ1~(j-i),

//也就是(1+j-i)*(j-i)/2。

因為資料範圍為10^6,所以必須進行優化,我們f[i][1]是由f[i+1]線性推出的,所以不需要進行優化,而f[i][0]由於從i+1~n,所以得進行優化。我們先考慮斜率優化,發現無法推出乙個單調製化的斜率,所以我們考慮使用單調佇列優化。

由於f[i][0]都是由f[j][1]推出的,所以我們維護f[j][1]的值,我們可以維護乙個單調遞增的佇列,如果新的f[i][1]小於舊的,就可以把舊的全部彈出佇列,因為從i往後更新肯定更優秀。

然後我們在佇列裡進行列舉,從隊尾tail列舉到隊頭top,如果對於其中的某數j,更新出的答案小於f[i][0],則將隊尾tail賦值為j,因為從tail~j-1的數字置在j之後,更新肯定不如j優。而大於j但目前答案不如j優的數先不刪去,因為(j-i+1)*(j-i)是以幾何級數增長的,之後的數更新時,可能j+1優於j。

code:

//這題資料很大,所以初始化得賦值2^60才行,1e18可能會wa

#include#define ll long long

using namespace std;

ll read()

ll n,a[1000005],f[1000005][2],top,tail;

struct nodeq[2000005];

ll sure(ll x)

int main()

f[i][1]=min(f[i+1][1],f[i+1][0])+a[i];

while(q[top].num>=f[i][1]) top--;

q[++top]=(node);

} printf("%lld",min(f[1][0],f[1][1]));

return 0;

}

bzoj 3156 防禦準備

第一行為乙個整數n表示戰線的總長度。第二行n個整數,第i個整數表示在位置i放置守衛塔的花費ai。共乙個整數,表示最小的戰線花費值。10 2 3 1 5 4 5 6 3 1 2 181 n 10 6,1 ai 10 9 暴力就不多說了 include include include include i...

BZOJ 3156 防禦準備

1 n放城堡 木偶,在第i位放城堡的 cost i 給出,放木偶的 cost i j i j為i右邊第乙個城堡 問最小花費普通 theta dp會掛 n leq 100000 需要斜率優化,為了方便,我們從左往右dp f i 為在這個點放城堡的最小花費 因為第n個必須放城堡 f i min j i ...

bzoj3156防禦準備

bzoj3156防禦準備 題意 n個檢查點,在第i個檢查點放置塔花費a i 放置木偶花費為該位置右邊最近乙個塔離它的距離。求最小花費。n 1000000 題解 從右往左處理。在第i個點放塔的費用f i min a i 用等差數列求和公式化簡後作斜率dp,具體看 反思 本弱公式總是推錯,要穩!1 in...