洛谷 P1725 琪露諾
阿新 • • 發佈:2019-02-10
print href || get new n) num 復雜 namespace
傳送門:洛谷 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; }
洛谷 P1725 琪露諾