Description
Input
Output
Sample Input
4
-1 10 -20
2 2 3 4
Sample Output
9
HINT
题解
斜率优化好像也没有什么特殊的技巧哇。
设
si
为
1…i
的和,
fi
为
1…i
的最大费用。
那么就愉快的推式子吧:
首先:
fi=max{fj+a(si−sj)2+b(si−sj)+c}
设 k<j 那么由j转移更优的话满足:
fj+a(si−sj)2+b(si−sj)+c>fk+a(si−sk)2+b(si−sk)+c
⇒si>fk−fj+bsj−bsk+as2k−as2j2ask−2asj
然后就是斜率优化经典的那一套理论啦。
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)) { if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); }
return x * f;
}
typedef long long ll;
const int N = 1000000 + 10;
ll s[N], f[N], a, b, c;
int n, q[N];
void init(){
n = read();
a = read(), b = read(), c =read();
int x;
for(int i = 1; i <= n; i++) x = read(), s[i] = s[i-1] + x;
}
inline double slope(int k, int j){
return (double)((f[k]-f[j]+b*s[j]-b*s[k]+a*s[k]*s[k]-a*s[j]*s[j])/(2*a*s[k]-2*a*s[j]));
}
inline ll sqr(ll x){return x * x;}
void work(){
int l = 0, r = 0;
for(int i = 1; i <= n; i++){
while(l < r && s[i] > slope(q[l], q[l+1])) l++;
int j = q[l];
f[i] = f[j] + a * sqr(s[i] - s[j]) + b * (s[i] - s[j]) + c;
while(l < r && slope(q[r], i) < slope(q[r-1], q[r])) r--;
q[++r] = i;
}
printf("%lld\n", f[n]);
}
int main(){
init();
work();
return 0;
}