设
表示只考虑前
个数的最大值,
表示前缀和,
显然:
假设
,且
比
更优,那么易得:
令
化简得:
所以我们得到:当 时, 比 更优等价于 号点和 号点之间的斜率小于 。
同理得到 时的等价条件,此时我们用单调队列维护即可。
参考代码:
#include<cstdio>
#define LL long long
const LL Max=1e6+5;
struct Node{
LL X,Y;
}Q[Max];
LL N,A,B,C,Left,Right,X[Max];
LL Cross(Node A,Node B,Node C){
return (B.X-A.X)*(C.Y-A.Y)-(B.Y-A.Y)*(C.X-A.X);
}
int main(){
LL I,J,K;
scanf("%lld%lld%lld%lld",&N,&A,&B,&C);
for(I=1;I<=N;I++){
scanf("%lld",&X[I]);X[I]+=X[I-1];
}
for(I=1;I<=N;I++){
while(Left<Right&&Q[Left].Y-2*A*X[I]*Q[Left].X<=Q[Left+1].Y-2*A*X[I]*Q[Left+1].X){
Left++;
}
Node Cur;
Cur.X=X[I];Cur.Y=Q[Left].Y-2*A*X[I]*Q[Left].X+2*A*X[I]*X[I]+C;
while(Left<Right&&Cross(Q[Right-1],Cur,Q[Right])<=0){
Right--;
}
Q[++Right]=Cur;
}
printf("%lld",Q[Right].Y+B*X[N]-A*X[N]*X[N]);
return 0;
}