洛谷 P1725 琪露诺
传送门:洛谷 P1725 琪露诺
算法分析:
设 \(dp[i]\) 为走到i位置的最大价值,则 \(dp[i]=max(dp[i],dp[i-j]+a[i])\) , 其中\(i\in[l,n]\),\(j\in[l,r]\)
最后答案即为 \(max\{dp[i]\}\),其中\(i\in[n-r+1,n]\)
此方法时间复杂度为 \(O(n^2)\) ,对于 \(maxN=2\times10^5\) 是超出的
再观察该方程,其中 \(dp[i],a[i]\) 为定值,只要求在\(i\in[l,n]\),\(j\in[l,r]\) 区间中 \(dp[i-j]\) 的最大值,使用单调队列算法来优化
时间复杂度:\(O(n)\)
#include<iostream>
#include<cstdio>
using namespace std;
const int maxN=200000;
int a[maxN+1],dp[maxN+10],q[maxN+1];
int n,l,r,ans=0,q_head,q_tail,num[maxN+1];
inline int read();
int main()
{
n=read(); l=read(); r=read();
for(int i=0;i<=n;i++)
a[i]=read();
q_head=1; q_tail=0;
for(int i=l;i<=n;i++)
{
while(dp[i-l]>=q[q_tail] && q_head<=q_tail) q_tail--;
num[++q_tail]=i-l;
q[q_tail]=dp[i-l];
while(i-num[q_head]>r-l) q_head++;
dp[i]=q[q_head]+a[i];
}
for(int i=n-r+1;i<=n;i++)
ans=max(ans,dp[i]);
printf("%d",ans);
return 0;
}
inline int read()
{
char ch=getchar();
int num=0,f=1;
while((ch<'0' || ch>'9') && ch!='-') ch=getchar();
if(ch=='-') {f=-1; ch=getchar();}
while(ch>='0' && ch<='9')
{
num=num*10+ch-'0';
ch=getchar();
}
return num*f;
}