首页 > 代码库 > 洛谷P1725 琪露诺 单调队列优化 DP

洛谷P1725 琪露诺 单调队列优化 DP

洛谷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\n",ans) ; 
45     
46     return 0 ; 
47 }

 

洛谷P1725 琪露诺 单调队列优化 DP