我数学好弱啊,这种题都能卡
设
f
i
f_i
fi为压缩完1~i的玩具的最优解,不难列出状态转移方程:
f
i
=
min
{
f
j
+
[
q
i
−
q
j
+
i
−
(
j
+
1
)
−
L
]
2
}
(
j
<
i
)
f_i=\min\{f_j+[q_i-q_j+i-(j+1)-L]^2\}(j<i)
fi=min{fj+[qi−qj+i−(j+1)−L]2}(j<i),其中
q
i
=
∑
k
=
1
i
C
k
q_i=\sum_{k=1}^iC_k
qi=∑k=1iCk
明显是
O
(
n
2
)
O(n^2)
O(n2)的式子,
n
≤
5
e
4
n \le 5e4
n≤5e4这种数据肯定过不去。
就要用到一些奇怪的优化了,比如斜率优化。
设
s
i
=
q
i
+
i
s_i=q_i+i
si=qi+i,
L
′
=
L
+
1
L'=L+1
L′=L+1
得
f
i
=
min
{
f
j
+
[
(
s
i
−
s
j
)
−
L
′
]
2
}
(
j
<
i
)
f_i=\min\{f_j+[(s_i-s_j)-L']^2\}(j<i)
fi=min{fj+[(si−sj)−L′]2}(j<i)
现在有两个数
j
,
k
j,k
j,k,满足
i
>
j
>
k
i>j>k
i>j>k,令状态
k
k
k优于状态
j
j
j,得
f
k
+
(
s
i
−
s
k
−
L
′
)
2
≤
f
j
+
(
s
i
−
s
j
−
L
′
)
2
遇
见
式
子
直
接
拆
,
得
f
k
+
[
s
i
−
(
s
k
+
L
′
)
]
2
≤
f
j
+
[
s
i
−
(
s
j
+
L
′
)
]
2
f
k
+
s
i
2
−
2
s
i
(
s
k
+
L
′
)
+
(
s
k
+
L
′
)
2
≤
f
j
+
s
i
2
−
2
s
i
(
s
j
+
L
′
)
+
(
s
j
+
L
′
)
2
化
简
,
得
f
k
−
2
s
i
(
s
k
+
L
′
)
+
(
s
k
+
L
′
)
2
≤
f
j
−
2
s
i
(
s
j
+
L
′
)
+
(
s
j
+
L
′
)
2
把
有
s
i
项
的
移
到
一
起
,
得
−
2
s
i
(
s
k
+
L
′
)
+
2
s
i
(
s
j
+
L
′
)
≤
−
f
k
+
f
j
−
2
s
i
(
s
j
+
L
′
)
+
2
s
i
(
s
k
+
L
′
)
−
(
s
k
+
L
′
)
2
+
(
s
j
+
L
′
)
2
两
边
都
乘
−
1
,
得
2
s
i
(
s
k
+
L
′
)
−
2
s
i
(
s
j
+
L
′
)
≤
f
k
−
f
j
+
2
s
i
(
s
k
+
L
′
)
−
2
s
i
(
s
k
+
L
′
)
+
(
s
k
+
L
′
)
2
−
(
s
j
+
L
′
)
2
s
i
[
2
(
s
k
+
L
′
)
−
2
(
s
j
+
L
′
)
]
≤
f
k
−
f
j
+
2
s
i
(
s
k
+
L
′
)
−
2
s
i
(
s
k
+
L
′
)
+
(
s
k
+
L
′
)
2
−
(
s
j
+
L
′
)
2
s
i
≤
f
k
−
f
j
+
2
s
i
(
s
k
+
L
′
)
−
2
s
i
(
s
k
+
L
′
)
+
(
s
k
+
L
′
)
2
−
(
s
j
+
L
′
)
2
2
(
s
k
+
L
′
)
−
2
(
s
j
+
L
′
)
设
X
i
=
2
s
i
,
Y
i
=
f
i
+
(
s
i
+
L
′
)
2
得
s
i
≤
Y
k
−
Y
j
X
k
−
X
j
嗯
,
这
么
眼
熟
,
高
中
书
上
的
斜
率
?
f_k+(s_i-s_k-L')^2 \le f_j+(s_i-s_j-L')^2\\ 遇见式子直接拆,得f_k+[s_i-(s_k+L')]^2 \le f_j+[s_i-(s_j+L')]^2\\ f_k+s_i^2-2s_i(s_k+L')+(s_k+L')^2 \le f_j+s_i^2-2s_i(s_j+L')+(s_j+L')^2\\ 化简,得f_k-2s_i(s_k+L')+(s_k+L')^2 \le f_j-2s_i(s_j+L')+(s_j+L')^2\\ 把有s_i项的移到一起,得-2s_i(s_k+L')+2s_i(s_j+L') \le -f_k+f_j-2s_i(s_j+L')+2s_i(s_k+L')-(s_k+L')^2+(s_j+L')^2\\ 两边都乘-1,得2s_i(s_k+L')-2s_i(s_j+L') \le f_k-f_j+2s_i(s_k+L')-2s_i(s_k+L')+(s_k+L')^2-(s_j+L')^2\\ s_i[2(s_k+L')-2(s_j+L')] \le f_k-f_j+2s_i(s_k+L')-2s_i(s_k+L')+(s_k+L')^2-(s_j+L')^2\\ s_i \le \frac{ f_k-f_j+2s_i(s_k+L')-2s_i(s_k+L')+(s_k+L')^2-(s_j+L')^2}{2(s_k+L')-2(s_j+L')}\\ 设X_i=2s_i,Y_i=f_i+(s_i+L')^2\\ 得 s_i \le \frac{Y_k-Y_j}{X_k-X_j}\\ 嗯,这么眼熟,高中书上的斜率?\\
fk+(si−sk−L′)2≤fj+(si−sj−L′)2遇见式子直接拆,得fk+[si−(sk+L′)]2≤fj+[si−(sj+L′)]2fk+si2−2si(sk+L′)+(sk+L′)2≤fj+si2−2si(sj+L′)+(sj+L′)2化简,得fk−2si(sk+L′)+(sk+L′)2≤fj−2si(sj+L′)+(sj+L′)2把有si项的移到一起,得−2si(sk+L′)+2si(sj+L′)≤−fk+fj−2si(sj+L′)+2si(sk+L′)−(sk+L′)2+(sj+L′)2两边都乘−1,得2si(sk+L′)−2si(sj+L′)≤fk−fj+2si(sk+L′)−2si(sk+L′)+(sk+L′)2−(sj+L′)2si[2(sk+L′)−2(sj+L′)]≤fk−fj+2si(sk+L′)−2si(sk+L′)+(sk+L′)2−(sj+L′)2si≤2(sk+L′)−2(sj+L′)fk−fj+2si(sk+L′)−2si(sk+L′)+(sk+L′)2−(sj+L′)2设Xi=2si,Yi=fi+(si+L′)2得si≤Xk−XjYk−Yj嗯,这么眼熟,高中书上的斜率?
图片来源:原题luogu题解
可以发现
s
i
s_i
si是单调上升的,然后非常simple画个图像(直接到洛谷上去找吧),发现是下凸包,我们只要找第一个
s
l
o
p
e
(
P
j
,
P
j
+
1
)
>
s
i
slope(P_j,P_{j+1})>s_i
slope(Pj,Pj+1)>si的点,那么既可以用二分
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn),也可以用单调队列
O
(
n
)
O(n)
O(n),不过需要四边形不等式证明一下(口胡?不会),GG。
好像就结束了啊,放个代码:
# include <bits/stdc++.h>
using namespace std;
const int N=5e4+5;
int n,L;
long long q[N];
long long dp[N];
int Q[N<<2];
int front,rear;
long long sq(long long x) {return x*x;}
long long X(int i)
{
return 2.0*q[i];
}
long long Y(int i)
{
return (dp[i])+sq((q[i])+(L+1));
}
long double slope(int i,int j)
{
return (long double)(Y(j)-Y(i))/(X(j)-X(i));
}
int main(void)
{
scanf("%d%d",&n,&L);
long long x;
for(int i=1;i<=n;i++)
{
scanf("%lld",&x);
q[i]=q[i-1]+x+1;
}
front=rear=0;
Q[++rear]=0;
for(int i=1;i<=n;i++)
{
while(front+1<rear&&slope(Q[front+1],Q[front+2])<=q[i]) front++;
int head=Q[front+1];
dp[i]=dp[head]+sq(q[i]-q[head]-L-1);
while(front+1<rear&&slope(Q[rear-1],i)<slope(Q[rear],Q[rear-1])) rear--;
Q[++rear]=i;
}
cout<<dp[n]<<endl;
return 0;
}