[bzoj1911][Apio2010]特别行动队

时间:2024-10-21 14:34:08

Description

[bzoj1911][Apio2010]特别行动队个元素[bzoj1911][Apio2010]特别行动队,可以将[bzoj1911][Apio2010]特别行动队个元素分成多组,每组的元素编号必须是连续的.

设每组的[bzoj1911][Apio2010]特别行动队[bzoj1911][Apio2010]特别行动队,则每组的价值公式为[bzoj1911][Apio2010]特别行动队.

求最大价值和.

Input

输入由三行组成。

第一行包含一个整数[bzoj1911][Apio2010]特别行动队,表示士兵的总数.

第二行包含三个整数[bzoj1911][Apio2010]特别行动队,价值公式中各项的系数.

第三行包含[bzoj1911][Apio2010]特别行动队个用空格分隔的整数[bzoj1911][Apio2010]特别行动队.

Output

输出一个整数,表示最大价值和。

Sample Input

4

-1 10 -20

2 2 3 4

Sample Output

9

HINT

 [bzoj1911][Apio2010]特别行动队

Solution

[bzoj1911][Apio2010]特别行动队表示前[bzoj1911][Apio2010]特别行动队个的最大价值和,

[bzoj1911][Apio2010]特别行动队.

这样是[bzoj1911][Apio2010]特别行动队的,显然过不了,所以考虑斜率优化.

[bzoj1911][Apio2010]特别行动队[bzoj1911][Apio2010]特别行动队时,

[bzoj1911][Apio2010]特别行动队

[bzoj1911][Apio2010]特别行动队

尽量将[bzoj1911][Apio2010]特别行动队分离:

[bzoj1911][Apio2010]特别行动队,

[bzoj1911][Apio2010]特别行动队

[bzoj1911][Apio2010]特别行动队,

[bzoj1911][Apio2010]特别行动队.

[bzoj1911][Apio2010]特别行动队的前提条件是

[bzoj1911][Apio2010]特别行动队.

整理得,[bzoj1911][Apio2010]特别行动队.

令 [bzoj1911][Apio2010]特别行动队,

则队列中的元素满足[bzoj1911][Apio2010]特别行动队

(若存在[bzoj1911][Apio2010]特别行动队,因为[bzoj1911][Apio2010]特别行动队是递增的,所以[bzoj1911][Apio2010]特别行动队[bzoj1911][Apio2010]特别行动队优,即[bzoj1911][Apio2010]特别行动队可以删去),

所以每次取元素时,将满足[bzoj1911][Apio2010]特别行动队[bzoj1911][Apio2010]特别行动队出队(因为[bzoj1911][Apio2010]特别行动队[bzoj1911][Apio2010]特别行动队优),然后取队首为[bzoj1911][Apio2010]特别行动队.

#include<set>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 1000001
using namespace std;
typedef long long ll;
ll f[N],s[N],q[N],a,b,c,n,h,t;
inline ll sqr(ll k){
return k*k;
}
inline ll y(ll k){
return a*sqr(s[k])+b*s[k]+c;
}
inline ll g(ll k){
return f[k]+a*sqr(s[k])-b*s[k];
}
inline ll func(ll k){
return a*sqr(k)+b*k+c;
}
inline double cmp(ll p,ll q){
return (double)(g(q)-g(p))/(double)(s[q]-s[p]);
}
inline void init(){
scanf("%lld%lld%lld%lld",&n,&a,&b,&c);
for(ll i=1;i<=n;i++){
scanf("%lld",&s[i]);
s[i]+=s[i-1];
}
for(ll i=1,k;i<=n;i++){
k=(a<<1)*s[i];
while(h<t&&cmp(q[h],q[h+1])>k) h++;
f[i]=f[q[h]]+func(s[i]-s[q[h]]);
while(h<t&&cmp(q[t],i)>cmp(q[t-1],q[t]))
t--;
q[++t]=i;
}
printf("%lld\n",f[n]);
}
int main(){
freopen("commando.in","r",stdin);
freopen("commando.out","w",stdout);
init();
fclose(stdin);
fclose(stdout);
return 0;
}