琪露诺
洛谷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; }