链接
题解
还债还债
对于这种和最大值/最小值有关的
考虑笛卡尔树式的分治结构
不会笛卡尔树也没有关系,当分治看就好了
先考虑
O
(
n
2
)
O(n^2)
O(n2)的DP怎么做
f
l
,
r
f_{l,r}
fl,r表示
[
l
,
r
]
[l,r]
[l,r]的答案
设
p
p
p为
[
l
,
r
]
[l,r]
[l,r]的最大值
可以得到转移
f
l
,
r
=
m
i
n
(
f
l
,
p
−
1
+
(
r
−
p
+
1
)
∗
h
[
p
]
,
f
p
+
1
,
r
+
(
p
−
l
+
1
)
∗
h
[
p
]
f_{l,r}=min(f_{l,p-1}+(r-p+1)*h[p],f_{p+1,r}+(p-l+1)*h[p]
fl,r=min(fl,p−1+(r−p+1)∗h[p],fp+1,r+(p−l+1)∗h[p]
可以发现,这个DP的转移,和
p
p
p有着密切关系
考虑分治优化这个东西
我们设
i
i
i作为最大值的区间是
[
L
i
,
R
i
]
[L_i,R_i]
[Li,Ri]
那么我们在
i
i
i这个点,他所管理的区间就是
[
L
i
,
R
i
]
[L_i,R_i]
[Li,Ri]
他维护的答案就是
f
L
i
,
L
i
,
f
L
i
,
L
i
+
1
,
f
L
i
,
L
i
+
2
.
.
.
f
L
i
,
R
i
f_{L_i,L_i},f_{L_i,L_i+1},f_{L_i,L_i+2}...f_{L_i,R_i}
fLi,Li,fLi,Li+1,fLi,Li+2...fLi,Ri
以及
f
L
i
,
R
i
,
f
L
i
+
1
,
R
i
,
f
L
i
+
2
,
R
i
.
.
.
f
R
i
,
R
i
f_{L_i,R_i},f_{L_i+1,R_i},f_{L_i+2,R_i}...f_{R_i,R_i}
fLi,Ri,fLi+1,Ri,fLi+2,Ri...fRi,Ri
那么在解决
[
L
i
,
R
i
]
[L_i,R_i]
[Li,Ri]之间,我们先解决
[
L
i
,
p
−
1
]
[L_i,p-1]
[Li,p−1],
[
p
+
1
,
R
i
]
[p+1,R_i]
[p+1,Ri]的答案
分治解决即可
那么就是合并答案了
先说
f
L
i
,
L
i
,
f
L
i
,
L
i
+
1
,
f
L
i
,
L
i
+
2
.
.
.
f
L
i
,
R
i
f_{L_i,L_i},f_{L_i,L_i+1},f_{L_i,L_i+2}...f_{L_i,R_i}
fLi,Li,fLi,Li+1,fLi,Li+2...fLi,Ri这一部分,另外一个部分类似
显然在
p
p
p之前的答案直接继承就好了
至于
p
p
p之后的,min函数显然会存在一个分界点,使得分界点前面的是
f
l
,
p
−
1
+
(
r
−
p
+
1
)
∗
h
[
p
]
f_{l,p-1}+(r-p+1)*h[p]
fl,p−1+(r−p+1)∗h[p],后面的是
f
p
+
1
,
r
+
(
p
−
l
+
1
)
∗
h
[
p
]
f_{p+1,r}+(p-l+1)*h[p]
fp+1,r+(p−l+1)∗h[p]
证明也十分简单,前面每次变大
h
p
h_p
hp,后面的每次变大不足
h
p
h_p
hp
在线段树上二分即可
那么我们的线段树就要资瓷:区间变成一个一次函数,区间加,还有单点询问
显然可以维护
至于询问,实际上我们要知道的是
f
l
,
p
−
1
f_{l,p-1}
fl,p−1这个的话,把循环挂在
[
l
,
p
−
1
]
[l,p-1]
[l,p−1]的最大值处的节点就好了
另外一个类似
取个min就行
代码
自然是没有的
#include<cstdio>
int main()
{
return 0;
}