我们设
F
i
F_i
Fi表示以
A
i
A_i
Ai结尾的最长不下降子序列的长度,那么
F
i
=
F_i=
Fi=什么呢?
因为它可以跟前面的拼接上,所以如果
A
i
>
=
A
j
(
i
>
j
)
A_i>=A_j(i>j)
Ai>=Aj(i>j),那么
F
i
=
m
a
x
(
F
i
,
F
j
+
1
)
(
加
上
A
i
)
F_i=max(F_i,F_j+1)(加上A_i)
Fi=max(Fi,Fj+1)(加上Ai)
方法2:
O
(
n
log
2
n
)
O(n\log_2n)
O(nlog2n) [
D
P
+
队
列
优
化
+
二
分
DP+队列优化+二分
DP+队列优化+二分]
建立一个队列,从
A
1
A_1
A1~
A
n
A_n
An遍历一遍,①如果队尾
F
t
a
i
l
<
=
A
i
F_{tail}<=A_i
Ftail<=Ai,那么将
A
i
A_i
Ai进入队列,表示
A
i
A_i
Ai可以使当前最长不下降子序列增长
1
1
1,②如果
F
t
a
i
l
>
A
i
F_{tail}>A_i
Ftail>Ai,那么我们发现它对当前是没有贡献的,但我们不是到它是否对之后的答案有贡献,那么我们可以从头到尾在队伍中找到第一个大于
A
i
A_i
Ai的数,将它修改成
A
i
A_i
Ai,这样其实对当前答案是没有影响的,但它可以使得之后的数和它,还有它前面的数,构成新的答案,从而保证我们答案的正确性
对于第②个情况,我们可以用二分来优化它的查找时间,变成
O
(
l
o
g
2
n
)
O(log_2n)
O(log2n)