P1725 琪露諾 題解(單調佇列)
阿新 • • 發佈:2018-11-04
題目連結
解題思路
單調佇列優化的\(dp\)。
狀態轉移方程:\(f[i]=max{f[i-l],f[i-l+1],...,f[i-r-1],f[i-r]}+a[i]\)
考慮單調佇列優化。
因為剛學,不是很熟悉單調佇列,特寫一篇詳細的解釋。
\(queue\) 陣列儲存一個佇列,他的頭部和尾部的下標分別用head和tail表示。
\(f\) 陣列是\(dp\)用到的陣列。
首先讀入每一個座標處的價值\(a[i]\)
列舉\(i\),從\(l\)到\(n\),分別計算\(f[i]\),當\(i+r>n\)時,儲存最大值ans。
單調佇列的註釋寫在程式碼中。
AC程式碼
#include<stdio.h> int i,n,l,r,a[200010],f[200010],ans=-2147483648;//這個題資料比較水,ans=0也能過,但理論上是不允許這樣的 int queue[200010],head=0,tail=-1; int main(){ scanf("%d%d%d",&n,&l,&r); for(i=0;i<n;i++){ scanf("%d",&a[i]); } for(i=l;i<=n;i++){ while(head<=tail&&queue[head]+r<=i)head++;//如果頭太靠前了,那就刪掉 while(head<=tail&&f[queue[tail]]<=f[i-l])tail--;//如果尾巴對應的a太小了,那就刪掉 //這兩句保證了單調佇列的不上升也即單調減特性,保證頭永遠是當前狀態的最佳狀態 queue[++tail]=i-l;//儲存上一次是從哪裡來的 f[i]=a[i]+f[queue[head]];//從上一步跳過來,跳到這裡的最大值 if(i>n-r&&f[i]>ans)ans=f[i]; } printf("%d",ans); return 0; }