洛谷P1725 琪露诺
单调队列优化 DP
题意:1--n 每个点都有一个权值,从当前点i可以到达i+l--i+r 之间的点,
动态规划 方程 为 f[ i ] = max(f[ i ],f[ k ] ) +a[ i ] i-r<=k<=i-l
然而这样复杂度 就为 n^2
因为相当于 dp 是在求 一段区间的最大值,而这个最大值就可以用O(n) 来维护
注意 这个O(n) 是均摊O(n) 即将所有固定区间长度的 最大值求出来 是 O(n)的
这样就把复杂度降到 O(n) 级别了
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <cstdlib> 5 #include <queue> 6 #include <iostream> 7 using namespace std ; 8 9 const int maxn = 200011 ; 10 struct node{ 11 int val,id ; 12 }; 13 deque <node> Q ; 14 int n,l,r,x,ans ; 15 int a[2*maxn],f[2*maxn] ; 16 17 inline int read() 18 { 19 char ch = getchar() ; 20 int x = 0 , f = 1 ; 21 while(ch<'0'||ch>'9') { if(ch=='-') f = -1 ;ch = getchar() ; } 22 while(ch>='0'&&ch<='9') x = x*10+ch-48,ch = getchar() ; 23 return x*f ; 24 } 25 26 int main() 27 { 28 n = read() ; l = read() ; r = read() ; 29 for(int i=0;i<=n;i++) 30 a[ i ] = read() ; 31 node p ; 32 for(int i=l;i<=n+r+3;i++) 33 { 34 x = i-l ; 35 while(!Q.empty()&&f[ x ] >= Q.back().val ) Q.pop_back() ; 36 p.val = f[ x ] ; 37 p.id = x ; 38 Q.push_back( p ) ; 39 while(!Q.empty()&& i-Q.front().id>r ) Q.pop_front() ; // > 这里是 跳过 r段 如果 包括初始 节点时 r+1段 40 f[ i ] = Q.front().val + a[ i ] ; 41 42 } 43 for(int i=n+1;i<=n+r+1;i++) if(f[ i ]>ans) ans = f[ i ] ; 44 printf("%d ",ans) ; 45 46 return 0 ; 47 }