这是一道斜率优化简单题,但是他不给清楚数据范围。注意:
0
≤
C
i
。
0\le C_i。
0≤Ci。
不会斜率优化,请戳这里。
设
f
[
i
]
表
示
对
前
i
个
单
词
进
行
处
理
的
最
低
费
用
,
s
为
c
的
前
缀
和
f[i]表示对前i个单词进行处理的最低费用,s为c的前缀和
f[i]表示对前i个单词进行处理的最低费用,s为c的前缀和。
则有:
f
[
i
]
=
m
i
n
f
[
j
]
+
(
s
[
i
]
−
s
[
j
]
)
2
+
m
(
0
≤
j
<
i
)
f[i]=min ~~~f[j]+(s[i]-s[j])^2+m ~~ (0\le j<i)
f[i]=min f[j]+(s[i]−s[j])2+m (0≤j<i)
化成
y
=
k
x
+
b
:
y=kx+b:
y=kx+b:
f
[
j
]
+
s
[
j
]
2
=
2
s
[
i
]
∗
s
[
j
]
+
f
[
i
]
−
s
[
i
]
2
+
m
f[j]+s[j]^2=2s[i]*s[j]+f[i]-s[i]^2+m
f[j]+s[j]2=2s[i]∗s[j]+f[i]−s[i]2+m
k
,
x
满
足
单
调
递
增
,
即
可
用
斜
率
优
化
做
。
k,x满足单调递增,即可用斜率优化做。
k,x满足单调递增,即可用斜率优化做。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=5e5+10;
int n,m,q[N],l,r;
ll f[N],s[N];
double y(int i){return (double)f[i]+s[i]*s[i];}
double x(int i){return (double)s[i];}
double slope(int i,int j)
{
return (y(i)-y(j))/(x(i)-x(j));
}
#define g getchar()
template<class o>//快读
void qr(o&x)
{
char c=g;bool v=x=0;
while(!( ('0'<=c&&c<='9') || c=='-' ))c=g;
if(c=='-')v=1,c=g;
while('0'<=c&&c<='9')x=x*10+c-'0',c=g;
if(v)x=-x;
}
#undef g
int main()
{
while(~scanf("%d",&n))
{
qr(m);
for(int i=1;i<=n;i++)
{
qr(s[i]);
if(!s[i]){i--,n--;continue;}//坑点。
s[i]=s[i]+s[i-1];
}
l=r=1;q[1]=0;
#define j q[l]
for(int i=1;i<=n;i++)
{
while(l<r&&slope(q[l],q[l+1])<=(double)(s[i]<<1))l++;
f[i]=f[j]+(s[i]-s[j])*(s[i]-s[j])+m;
while(l<r&&slope(q[r-1],q[r])>=slope(q[r],i))r--;
q[++r]=i;
}
#undef j
printf("%lld\n",f[n]);
}
return 0;
}