bzoj1911 [Apio2010]特别行动队

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1911

【题解】

权当复习斜率优化了。

再过一遍基本式子。

本题dp方程为f[i] = max{f[j] + a(s[i]-s[j])^2 + b(s[i]-s[j]) + c}

1. 假设j<k,j没有k优

那么f[j]+a(s[i]-s[j])^2 + b(s[i]-s[j]) + c <= f[k] + a(s[i]-s[k])^2 + b(s[i]-s[k]) + c   ……①

若现在到了i+1,即证下式是否成立

f[j]+a(s[i+1]-s[j])^2 + b(s[i+1]-s[j]) + c <= f[k] + a(s[i+1]-s[k])^2 + b(s[i+1]-s[k]) + c 

将①代入,即证:

2ax[i+1](s[i]-s[j])+bx[i+1] <= 2ax[i+1](s[i]-s[k])+bx[i+1]

即证a(s[i]-s[j])<=a(s[i]-s[k]),由于a是负数,即证s[k]>=s[j],显然成立。

故有决策单调性

2. 推斜率式

根据①得到:

((f[j]+as[j]^2-bs[j])-(f[k]+as[k]^2-bs[k]))/(2a(s[j]-s[k])) <= s[i]

那么s[i]单调递增,相当于维护一个下凸壳。

那么直接维护就行了

尽量把左右都化成正的好搞啊

# include <stdio.h>
# include <string.h>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 1e6 + 10;
const int mod = 1e9+7;

# define RG register
# define ST static

int n, A, B, C, a[M]; 
int q[M], head, tail; 
ll f[M], s[M];

inline ld slop(int j, int k) {
    return (ld)((s[j]*s[j]*A-s[j]*B+f[j])-(s[k]*s[k]*A-s[k]*B+f[k]))/(ld)((s[j]-s[k])*2*A); 
}

int main() {
    scanf("%d%d%d%d", &n, &A, &B, &C);
    for (int i=1; i<=n; ++i) {
        scanf("%d", a+i);
        s[i] = s[i-1] + a[i];
    }
    
    head = 1, tail = 1; q[tail] = 0;
    for (int i=1; i<=n; ++i) {
        while(head < tail && slop(q[head], q[head+1]) <= (ld)s[i]) ++head;
        int t = q[head];
        f[i] = f[t] + (s[i]-s[t])*(s[i]-s[t])*A + (s[i]-s[t])*B + C;
        while(head < tail && slop(q[tail-1], q[tail]) > slop(q[tail], i)) --tail;
        q[++tail] = i; 
    }
    printf("%lld\n", f[n]); 
    return 0;
}
View Code

 

posted @ 2017-04-27 21:16  Galaxies  阅读(127)  评论(0编辑  收藏  举报