【单调队列优化dp】uestc 594 我要长高

http://acm.uestc.edu.cn/#/problem/show/594

【AC】

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=5e4+2;
 5 const int inf=0x3f3f3f3f;
 6 int n,c;
 7 int cur;
 8 int dp[2][maxn];
 9 int q[maxn];
10 int main()
11 {
12     while(scanf("%d%d",&n,&c)!=EOF)
13     {
14         int x;
15         scanf("%d",&x);
16         cur=0;
17         for(int i=1;i<x;i++) dp[cur][i]=inf;
18         for(int i=x;i<=100;i++) dp[cur][i]=(i-x)*(i-x);
19         for(int i=1;i<n;i++)
20         {
21             scanf("%d",&x);
22             cur^=1;
23             int head=1,tail=0;
24             for(int j=1;j<=100;j++)
25             {
26                 while(head<=tail&&q[tail]>=dp[cur^1][j]-c*j) tail--;
27                 q[++tail]=dp[cur^1][j]-c*j;
28                 if(j<x) dp[cur][j]=inf;
29                 else dp[cur][j]=q[head]+j*c+(j-x)*(j-x);
30             }
31             head=1,tail=0;
32             for(int j=100;j>=x;j--)
33             {
34                 while(head<=tail&&q[tail]>=dp[cur^1][j]+c*j) tail--;
35                 q[++tail]=dp[cur^1][j]+c*j;
36                 dp[cur][j]=min(dp[cur][j],q[head]-j*c+(j-x)*(j-x));
37             }            
38         }
39         int ans=inf;
40         for(int i=x;i<=100;i++)
41         {
42             ans=min(ans,dp[cur][i]);
43         }
44         printf("%d
",ans);
45     }
46     return 0;
47 }
单调队列优化dp

【坑】

第一种情况for循环要从1开始,而不是从x开始,虽然只有当j>=x时才能更新dp[cur][j],但q[head]有可能是dp[cur^1][j]在j<x时的值,换句话说j要考虑dp[cur^1]的所有可能值

另外,这道题用滚动数组节省了空间,因为每个韩子都只和他之前的一个有关,当然,第一个韩子要先处理好

原文地址:https://www.cnblogs.com/itcsl/p/7449962.html