题解 P1725 【琪露诺】
感觉还是滑动窗口解决这个问题比较好,根据自己的习惯,一直使用deque来实现的滑动窗口,STL神奇,这东西真好,当然自己手工用数组写也行的。给定窗口区间[l,r], 用滑动窗口找到区间的dp最大值max,然后根据 dp[i]=max+a[i],就可以了。写的时候的误区:总是局限于DP 的前几个数,后来想到从0位置,最先跳到L位置,所以L是我们第一个dp循环的下标;另一个误区就是窗口的大小,窗口大小是固定的 r-l+1就是,所以窗口出队列的条件就是 i-front().num>=(r-l+1);i代表进入队列窗口元素的下标,最后从n开始找就行了,本题数据有点水。下面是代码:
#include <iostream>
#include <deque>
using namespace std;
const int inf=0x3f3f3f3f;
struct sa
{
int val;
int num;
};
int dp[200001];
int a[200001];
deque <sa> v;
int main()
{ struct sa tmp;
int n,l,r,p;
cin>>n>>l>>r;
for(int i=0;i<=n;i++)
cin>>a[i];
p=0; dp[p]=0;
for(int i=l;i<=n;i++)
{
while(!v.empty()&&dp[p]>=v.back().val)
v.pop_back();
tmp.num=p;tmp.val=dp[p];
v.push_back(tmp);
//cout<<"dp ="<<dp[p].val<<endl;
if (p-v.front().num>=(r-l+1))//这里是p不是i
v.pop_front();
dp[i]=v.front().val+a[i];
//cout<<p<<" "<<v.front().val<<" "<<dp[i].val<<endl;
p++;
}
int ans=-inf;
for(int i=n-r+1;i<=n;i++)
ans=max(ans,dp[i]);
cout<<ans<<endl;
return 0;
}