UESTC 594 我要长高 dp单调队列
//戳这里:594
//补一发之前的单调队列 dp
1 #include "bits/stdc++.h" 2 using namespace std; 3 int N, C; 4 int h[50010]; 5 6 int dp[50010][110]; 7 struct Queue 8 { 9 int value; 10 }q[110], tmp; 11 int front, rear; 12 13 //j > k 时, 14 //dp[i][j] = min(dp[i - 1][k] + (j - k) * C + (j - h[i]) * (j - h[i])); 15 //dp[i][j] = min(dp[i - 1][k] - k * C) + j * C + (j - h[i]) * (j - h[i]); 16 17 int main() 18 { 19 while(scanf("%d%d", &N, &C) != EOF) { 20 //初始化 21 memset(dp, 0x3f, sizeof(dp[0]) * (N + 1)); 22 //输入 23 int i; 24 for(i = 1; i <= N; ++i) { 25 scanf("%d", &h[i]); 26 } 27 //k 不需要优化的情况 28 int j; 29 for(j = h[1]; j <= 100; ++j) { 30 dp[1][j] = (j - h[1]) * (j - h[1]); 31 } 32 //从 2 开始dp 33 for(i = 2; i <= N; ++i) { 34 front = rear = 1; 35 for(j = h[i - 1]; j <= 100; ++j) { 36 tmp.value = dp[i - 1][j] - j * C; 37 for( ; front < rear && tmp.value < q[rear - 1].value; --rear); 38 q[rear++] = tmp; 39 if(j >= h[i]) { 40 dp[i][j] = q[front].value + j * C + (j - h[i]) * (j - h[i]); 41 } 42 } 43 front = rear = 1; 44 for(j = 100; j >= h[i]; --j) { 45 tmp.value = dp[i - 1][j] + j * C; 46 for( ; front < rear && tmp.value < q[rear - 1].value; --rear); 47 q[rear++] = tmp; 48 dp[i][j] = min(dp[i][j], q[front].value - j * C + (j - h[i]) * (j - h[i])); 49 } 50 } 51 int res = 0x3f3f3f3f; 52 for(i = 1; i <= 100; ++i) { 53 res = min(res, dp[N][i]); 54 } 55 printf("%d\n", res); 56 } 57 }