题目描述
因为是从别人博客里斜率优化分类一栏找的题目,所以…这题被我秒了。
显然先预处理前缀和
s(i)=∑ik=1xi
设
d(i)
为将前
i
个士兵分组的最大修正后战斗力。
设
KiXjBiYj====2a×s(i)s(j)d(i)−a×s(i)2−b×s(i)−cd(j)+a×s(j)2−b×s(j)
直线解析式为 KiXj+Bi=Yj 其中斜率 Ki 单减, Xj 单增。
代码
#include<cstdio>
#include<iostream>
#include<cstring>
#define k(A) (2*a*s[A])
#define x(A) s[A]
#define b(A) (d[A]-a*s[A]*s[A]-b*s[A]-c)
#define y(A) (d[A]+a*s[A]*s[A]-b*s[A])
using namespace std;
const int maxn=1000010;
long long d[maxn],s[maxn];
int q[maxn],n,a,b,c;
double slope(int i,int j){
return 1.0*(y(i)-y(j))/(x(i)-x(j));
}
int main(){
cin>>n>>a>>b>>c;
s[0]=q[0]=d[0]=0;
for(int i=1;i<=n;i++){
int x;
scanf("%d",&x);
s[i]=s[i-1]+x;
}
int head=0,tail=0;
for(int i=1;i<=n;i++){
while(head<tail&&slope(q[head],q[head+1])>k(i)) head++;
d[i]=-(k(i)*x(q[head])-y(q[head])-a*s[i]*s[i]-b*s[i]-c);
while(head<tail&&slope(q[tail-1],q[tail])<=slope(q[tail],i)) tail--;
q[++tail]=i;
}
cout<<d[n]<<endl;
}