衆所周知,琪露諾是以笨蛋聞名的冰之妖精。node
題目:https://www.luogu.org/problemnew/show/P1725優化
顯然,是一道DP題(很噁心顯然二字,如今來噁心大家)spa
狀態轉移是dp[i]=max(dp[k])+a[i];code
跳到當前位置的最大值是前面能跳到到這裏的全部位置的最大值加上當前位置的冰凍值;blog
爲何要用雙端隊列呢(由於爽啊)隊列
這個很裸了已經,滑動窗口的思想。就是純DP是會T的,因此咱們尋找最大值時要優化時間;get
若是當前的值比隊列中的值大,就把隊列中的已有元素彈出(由於咱們是從前日後遍歷的,一個位置在前且值小的元素是不會作出任何貢獻的);string
代碼it
#include<cstdio> #include<cstring> #include<deque> #include<algorithm> using namespace std; const int maxn=200100; struct node { int val;//DP最大值 int num;// }; int n,a[maxn],l,r; int dp[maxn]; deque <node> s; int main() { scanf("%d%d%d",&n,&l,&r); for(int i=0;i<=n;i++) { scanf("%d",a+i); } int tail=0;dp[tail]=0; node x; for(int i=l;i<=n;i++)//從0開始轉移向l處 { while(s.size()&&dp[tail]>=s.back().val) { s.pop_back(); }//無用值彈出 x.num=tail;x.val=dp[tail]; s.push_back(x);//加入新值 if(tail-s.front().num>=(r-l+1)) s.pop_front();//隊列的長度 dp[i]=s.front().val+a[i];//此時隊列最前面的是前面能到達i的最大值 tail++; } int ans=-maxn; for(int i=n-r+1;i<=n;i++) { ans=max(ans,dp[i]); } printf("%d",ans); return 0; }