传送门
SOL
(题面都没有描述清楚,到底c能不能是负数)(不然就要平衡树维护了)
f
[
i
]
=
f
[
j
]
+
(
s
[
i
]
−
s
[
j
]
)
2
+
m
f[i]=f[j]+(s[i]-s[j])^2+m
f[i]=f[j]+(s[i]−s[j])2+m
f
[
j
]
+
s
[
j
]
2
=
2
∗
s
[
i
]
∗
s
[
j
]
−
s
[
i
]
2
−
m
+
f
[
i
]
f[j]+s[j]^2=2*s[i] *s[j] - s[i]^2 -m + f[i]
f[j]+s[j]2=2∗s[i]∗s[j]−s[i]2−m+f[i]
x
=
s
[
j
]
,
y
=
f
[
j
]
+
s
[
j
]
2
,
k
=
2
∗
s
[
i
]
x=s[j],y=f[j]+s[j]^2,k=2*s[i]
x=s[j],y=f[j]+s[j]2,k=2∗s[i]
CODE
#include<bits/stdc++.h>
#define pf printf
#define sf scanf
#define ll long long
using namespace std;
const int maxn=5e5+10;
ll f[maxn],s[maxn],n,m;
inline ll y(int a,int b){return f[a]+s[a]*s[a]-f[b]-s[b]*s[b];}
inline ll x(int a,int b){return s[a]-s[b];}
int q[maxn],head,tail=0;
/*
f[i]=f[j]+(s[i]-s[j])^2+m
f[j]+s[j]^2=2*s[i] *s[j] - s[i]^2 -m + f[i];
*/
signed main (){
while(~sf("%d%d",&n,&m)){
for(int i=1;i<=n;++i)sf("%lld",&s[i]),s[i]+=s[i-1];
head=tail=1;q[head]=0;f[0]=0;
for(int i=1;i<=n;++i){
while(head<tail&&y(q[head+1],q[head])<=2*s[i]*x(q[head+1],q[head]))++head;
int j=q[head];
f[i]=f[j]+(s[i]-s[j])*(s[i]-s[j])+m;
while(head<tail&&y(q[tail],q[tail-1])*x(i,q[tail])>=y(i,q[tail])*x(q[tail],q[tail-1]))--tail;
q[++tail]=i;
}
cout<<f[n]<<"\n";
}
return 0;
}