比较模板的一道题(? 没调就直接过了
首先看式子
\[dp_i = dp_j + a\times (sum_i - sum_j) ^ 2 + b \times (sum_i - sum_j) + c
\]
不难拆分,我们可以得到
\[a \times sum_j ^ 2- b \times sum_j + dp_j = 2a \times sum_i \times sum_j + dp_i - b \times sum_i - c
\]
直接代入一次函数 \(y = kx + b\) 即可
然后就是单调队列维护上凸壳,这个跟下凸壳是一模一样的,改一下单调队列就行
然后就没了
#include <bits/stdc++.h>#define N 1000007
#define int long longusing namespace std;int h , t , n , a , b , c , sum[N] , q[N] , dp[N];inline int P(int x) {return x * x;
}inline int x(int i) {return sum[i];
}inline int y(int i) {return a * P(sum[i]) - b * sum[i] + dp[i];
}inline double slope(int i , int j) {return (y(i) - y(j)) * 1.0 / (x(i) - x(j));
}signed main() {ios :: sync_with_stdio(0) , cin.tie(0) , cout.tie(0);cin >> n >> a >> b >> c;for(register int i = 1; i <= n; ++i) {cin >> sum[i]; sum[i] += sum[i - 1];}h = 1, t = 0;for(register int i = 1; i <= n; ++i) {while(h < t && slope(i - 1 , q[t]) >= slope(q[t - 1] , q[t])) {--t;}q[++t] = i - 1;while(h < t && slope(q[h] , q[h + 1]) >= 2 * a * sum[i]) {++h;}int target = q[h];dp[i] = dp[target] + P(sum[i] - sum[target]) * a + (sum[i] - sum[target]) * b + c;} cout << dp[n];return 0;
}