BZOJ4709 檸檬(動態規劃,單調棧)

2021-08-21 10:36:21 字數 2451 閱讀 6624

bzoj

從左取和從右取沒有區別,本質上就是要分段。 設f

[i] f[i

]表示前

i i

個位置的最大值。

那麼相當於我們列舉乙個前面的位置

j' role="presentation">j

j,然後找到這一段中最大的s0

t2s 0t

2但是這樣子很不優秀。

我們貪心的思考一下,既然這一段最後加起來只能變成某乙個s0

s 0,

那麼,我們這一段開頭和結尾都一定要是s0

s 0,

否則我們把結尾那些不等於s0

s

0的單獨分開一段,

這樣子的答案一定不會更差,字首同理。

因此每次的s0

s

0一定由前面的某個s0

s

0轉移過來。

轉移是f[i

]=f[

j−1]

+s[i

]t2 f[i

]=f[

j−1]

+s[i

]t

2,其中t2

t

2是[j

,i] [j,

i]

中s[i]

s [i

]的個數。 發現t

2 t

2增長很快於y=

x y=x

,顯然這個式子是具有決策單調性的。

如果當前位置

k<

j k

<

j,那麼一旦

k k

的轉移優於了

j' role="presentation">j

j,那麼

k k

就永遠優於

j' role="presentation">j

j了。(這不顯然嗎?

那麼,對於每乙個

s s

都維護乙個單調棧(ve

ctor

' role="presentation">vec

torv

ecto

r) 每次將後面不優的全部彈出去,然後進行轉移。

注意幾點:

首先是不優的靠計算,記錄一下當前位置的字首

t t

的值,然後每次二分檢查單調棧裡面的第二個元素是否優於棧頂元素,也就是二分查詢一下超過的時間。

還有一種可能出現的情況,即當前第二個元素不比棧頂優秀,但是第三個元素比棧頂優秀。

對於棧頂的幾個元素,假設

a<

b<

c<

d' role="presentation">a

<

b<

c<

b<

c<

d,如果

a a

超過c' role="presentation">c

c的時間要早於

b b

超過d' role="presentation">d

d的時間。

那麼當b

b

超過d' role="presentation">d

d的時候,

a a

早就超過

d' role="presentation">d

d了,那麼

b b

是沒有意義的。

所以對於當前位置

i' role="presentation">i

i,我們檢查棧頂元素和第二個元素超過

i i

的時間

如果第二個元素超過

i' role="presentation">i

i的時間更早,那麼第乙個元素就沒有意義了,可以直接彈掉。

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

#define ll long long

#define rg register

#define max 111111

inline

int read()

ll f[max];

vector

g[max];

int n,a[max],num[max],s[max];

ll calc(int j,int x)

int time(int x,int y)

return ret;

}int main()

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

}

bzoj4709 檸檬 單調棧,DP,斜率優化

目錄錯誤 s是值等於a i 的字首和 轉移方程 f i max f i f j 1 a i s i s j 1 s i s j 1 不難寫出暴力方程 by wxyww baoli memset f,0x3f,sizeof f f 0 0 for int i 1 i n i 關於此題的單調性 特性1每...

BZOJ1037動態規劃

資料範圍很小,可以用4維儲存下前i個男孩j個女孩,從這一位往前的所有點中男 女的差最大為x,女 男為y的方案數 主動遞推 f i 1 j x 1 max y 1 0 f i j x y f i j 1 max x 1 0 y 1 f i j x y 最後答案為 sigma x sigma y f n...

BZOJ1040 騎士(動態規劃)

bzoj 對於每一組厭惡的關係 顯然是連邊操作 如果是一棵樹的話 很顯然的樹型dp 但是,現在相當於有很多個基環 也就是在一棵樹的基礎上再加了一條邊 這個時候怎麼辦,暴力拆掉基環 拆掉任意一條邊 跑兩遍dp 計算出強制不選兩個點中某乙個的最大值 此時就是這個基環的最大值 不用拆掉所有的邊,因為只要拆...