# [Bzoj1911][Apio2010]特别行动队(斜率优化)

dp[i]为1-i的序列的最优解。sum[i]为前缀和,$D(i)=ax^{2}+bx+c$

$dp[j]+a(sum[i]-sum[j])^{2}-b(sum[i]-sum[j])+c\geq dp[k]+a(sum[i]-sum[k])^{2}-b(sum[i]-sum[k])+c$

$dp[j]+asum[j]^{2}-bsum[j]-(dp[k]+asum[k]^{2}-bsum[k])\geq 2asum[i](sum[j]-sum[k])$

$\frac{dp[j]+asum[j]^{2}-bsum[j]-(dp[k]+asum[k]^{2}-bsum[k])}{sum[j]-sum[k]}\geq 2asum[i]$

$\frac{f[j]-f[k]}{T[j]-T[k]}\geq 2asum[i]$

 1 #include<bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 const  int maxn = 1e6 + 10;
5 ll sum[maxn], q[maxn], dp[maxn], que[maxn];
6 int n, a, b, c;
7 ll f(int j, int k) {
8     return dp[j] + a * sum[j] * sum[j] - b * sum[j] - (dp[k] + a * sum[k] * sum[k] - b * sum[k]);
9 }
10 ll T(int j, int k) {
11     return sum[j] - sum[k];
12 }
13 ll D(int x) {
14     return a * x*x + b * x + c;
15 }
16 int main() {
17     scanf("%d", &n);
18     scanf("%d%d%d", &a, &b, &c);
19     for (int i = 1; i <= n; i++)
20         scanf("%lld", &q[i]), sum[i] = sum[i - 1] + q[i];
21     int l = 1, r = 1;
22     que[l] = 0;
23     for (int i = 1; i <= n; i++) {
24         while (l < r&&f(que[l + 1], que[l]) >= 2 * a*sum[i] * T(que[l + 1], que[l]))
25             l++;
26         dp[i] = dp[que[l]] + D(sum[i] - sum[que[l]]);
27         while (l < r && f(que[r], que[r - 1])*T(i, que[r]) < T(que[r], que[r - 1])*f(i, que[r]))
28             r--;
29         que[++r] = i;
30     }
31     printf("%lld\n", dp[n]);
32 }

posted @ 2019-09-04 11:44  祈梦生  阅读(137)  评论(0编辑  收藏  举报