洛谷 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;
}
posted @ 2019-02-10 15:57  常青藤的花语  阅读(225)  评论(0编辑  收藏  举报

知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。