他们oj挂掉啦, 我先保存一下代码。。。
直接dp复杂度, n * 100 * 100, 我们可以将前一个人的信息丢进单调队列中去,可以优化成n * 100;
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int,int> #define piii pair<int, pair<int,int> > using namespace std; const int N = 5e4 + 7; const int M = 10 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-6; int n, c, head1, head2, rear1, rear2; int sk1[N], sk2[N], a[N], dp[N][101]; void init() { for(int i = 1; i <= n; i++) { for(int j = 0; j <= 100; j++) { dp[i][j] = inf; } } head1 = head2 = 0; rear1 = rear2 = 0; } int main() { while(scanf("%d%d", &n, &c) != EOF) { init(); for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); } for(int j = a[1]; j <= 100; j++) { dp[1][j] = (j - a[1]) * (j - a[1]); } for(int i = 2; i <= n; i++) { rear1 = rear2 = 0; head1 = head2 = 0; for(int j = 0; j <= 100; j++) { while(head1 < rear1 && dp[i - 1][j] + c * j < dp[i - 1][sk1[rear1 - 1]] + c * sk1[rear1 - 1]) rear1--; sk1[rear1++] = j; } for(int j = 100; j >= 0; j--) { while(head2 < rear2 && dp[i - 1][j] - c * j < dp[i - 1][sk2[rear2 - 1]] - c * sk2[rear2 - 1]) rear2--; sk2[rear2++] = j; } for(int j = a[i]; j <= 100; j++) { while(head1 < rear1 && sk1[head1] < j) head1++; if(head1 < rear1) dp[i][j] = dp[i - 1][sk1[head1]] + c * sk1[head1] + (j - a[i]) * (j - a[i]) - c * j; } for(int j = 100; j >= a[i]; j--) { while(head2 < rear2 && sk2[head2] > j) head2++; if(head2 < rear2) dp[i][j] = min(dp[i][j], dp[i - 1][sk2[head2]] - c * sk2[head2] + (j - a[i]) * (j - a[i]) + c * j); } } int ans = inf; for(int j = a[n]; j <= 100; j++) { ans = min(ans, dp[n][j]); } printf("%d\n", ans); } return 0; } /* */