琪露诺

洛谷P1725 琪露诺

交了15遍,差点砸电脑,我对自己无语了,为什么不好好想,耐下心来。。第一感觉是dp,然后没仔细想,瞎觉得好像不是,然后没管住自己,看了标签,果然是dp,后悔自己为何没好好想想。不过自己写出了转移方程,很好,然后编程的时候没有按方程转移,再次无语。。最后确定答案时,范围卡小了,就老是不对,惨痛的教训。。。。。

思路:对于一个位置i,它只能跳到[i+l,i+r]位置上,我们反过来想,这个位置i只能由[i-r,i-l]的位置转移过来,用单调递减队列维护[i-r,i-l]上的f值,f[i]代表走到i的最大值sum,唉。。。

 //17.10.3

今天又看了一遍,发现我竟然做过单调队列优化dp,我都忘了,它满足移动和转移的条件。我要再打一个普通版的,看看优化的效果怎么样。

#include<bits/stdc++.h>
using namespace std;
int n,a[200001],l,r,top,tai;
long long f[200001],ans=-99999999;
int q[200001];
int main()
{
    cin>>n>>l>>r;
    for(int i=0;i<=n;i++) cin>>a[i];
    f[0]=a[0];
    for(int i=l;i<=n;i++)
    {
        while(top<=tai&&f[q[tai]]<=f[i-l])tai--;
         tai++;        
        q[tai]=i-l;
        while(q[tai]-q[top]>r-l) top++;
        f[i]=a[i]+f[q[top]];
    }    
    for(int i=n-r;i<=n;i++)
    ans=max(ans,f[i]);
    ans=max(ans,f[n]);
    cout<<ans<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/war1111/p/7299100.html