單調佇列優化DP LNSYOJ 106 猴子

2022-08-03 22:33:15 字數 1973 閱讀 8989

這是一道思路比較簡單但是除錯極其毒瘤的一道題目!

乙個猴子找到了很多香蕉樹,這些香蕉樹都種在同一直線上,而猴子則在這排香蕉樹的第一棵樹上。這個猴子當然想吃盡量多的香蕉,但它又不想在地上走,而只想從一棵樹跳到另一棵樹上。同時猴子的體力也有限,它不能一次跳得太遠或跳的次數太多。每當他跳到一棵樹上,它就會把那棵樹上的香蕉都吃了。那麼它最多能吃多少個香蕉呢?

輸入第一行為三個整數,分別是香蕉樹的棵數n

'>n

n,猴子每次跳躍的最大距離d

'>d

d,最多跳躍次數m

'>m

m。 下面n

'>n

n行每行包含兩個整數ai,

bi'>ai,bi

ai,bi,分別表示每棵香蕉樹上的香蕉數,以及這棵樹到猴子所在樹的距離。輸入保證這些樹按照從近到遠排列,並且沒有兩棵樹在同一位置。b

0'>b0

b0總是為0。

輸出只有一行,包含乙個整數,為猴子最多能吃到的香蕉數。

input

5 5 2

6 08 3

4 56 7

9 10

output

20

對於30%的資料,1≤m

100'>1≤m

1≤m對於50%的資料,1≤m

2000

'>1≤m

1≤m對於100%的資料,1≤m

5000,a

i≤10000,b

i≤10000,d

≤10000

'>1≤m

1≤m時間限制:1

s'>1s

1s空間限制:256

mb'>256mb

256mb

'>首先是狀態轉移方程dp[k][i]表示到第i棵數已經跳了k步的最多香蕉數

256mb

'>那麼轉移就是dp[k][i]=max(dp[k-1][q[head]]+val[i],dp[k][i]);

256mb

'>然後呢就是毒瘤的單調佇列時間

就是這種資料結構,把它弄成單調的,head彈出,tail插入;

在陣列裡是把整個佇列倒過來放進去的

因為是單調佇列

所以插入時候tail--找到要插的位置,然後再++tail位置插進去

彈出時候head++,就彈出了

也就是說在陣列裡head在左,tail在右,可以腦補這個佇列就躺在陣列裡

一定要注意head要<=tail,要不可能會死迴圈(網上有個**就被我hack了)

這道題有一些注意的地方;

有幾組資料比較毒瘤,有可能有兩個樹之間距離很大,導致後面的樹全都去不了(見16行特判,被卡掉了30分),這時候需要特殊處理(我直接輸出,會跑的很快2333)

上**!

1 #include2 #include3 #include4 #include5
using

namespace

std;

6int n,d,m,head=1,tail=1,ans=-1;7

int val[5111],s[5111],dp[5111][5111],q[5111];8

intmain()

923 q[tail]=k;

24for(int i=k+1;i<=n;i++)

2533}34

for(int i=1;i<=n;i++)ans=max(ans,dp[m][i]);

35 printf("

%d\n

",ans);

36return0;

37 }

單調佇列優化

單調佇列是一種嚴格單調的佇列,可以單調遞增,也可以單調遞減。隊首位置儲存的是最優解,第二個位置儲存的是次優解。單調佇列可以有兩個操作 1 插入乙個新的元素,該元素從隊尾開始向隊首進行搜尋,找到合適的位置插入之,如果該位置原本有元素,則替換它。2 在過程中從隊首刪除不符合當前要求的元素。單調佇列實現起...

單調佇列 優化DP

佇列元素保持單調遞增 減 而保持的方式就是通過插隊,把隊尾破壞了單調性的數全部擠掉,從而使佇列元素保持單調。單調佇列的作用 優化dp。許多單調佇列優化的dp可以使複雜度直接降維,下面就以最簡單的一道題為例 在某兩座城市之間有 n 個烽火台,每個烽火台發出訊號都有一定代價。為了使情報準確地傳遞,在連續...

單調佇列優化dp

形如f i max wi的問題都可以用單調佇列優化。例題 板題 注意乙個地方 求完所有的f後 ans不是f n 而是後面的一段字尾的f 注意字尾的左端點。很顯然是rmq問題 計算字首和sum i 對於固定的右端點 i,我們想讓答案最大等價於max,可以用個單調佇列維護。但是隨便乙個資料結構直接on ...