LIS学习笔记
前情提要:蓝桥杯校赛压轴题,是道朴素最长上升子序列板子题;没做出来,故学习记录一下

题目链接
设原数列为 1,2,4,1,3,4,$f(x)$ 表示以第 $i$ 个数为结尾的最长上升子序列的长度
| n | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| $a_i$ | 1 | 2 | 4 | 1 | 3 | 4 |
| $f(n)$ | 1 | 2 | 3 | 1 | 3 | 4 |
代码实现
- 读入数据
- 大循环开始,从 $1$ 到 $n$,计算 $f_i$,记得初始值是 $1$
- 小循环,从 $1$ 到 $i−1$,如果 $a_j$ 小于 $a_i$ 的话,说明这个数可以和 $f_i$ 组成上升子序列,则 $f_i$ 取 $max(f_i,f_j+1)$
- 寻找最大值
具体代码
1 | #include<iostream> |
二分优化
我们定义一个数组 tails,其中 tails[k] 表示长度为 $k+1$ 的上升子序列的最小尾元素。该数组帮助我们追踪可能构成的上升子序列的最小值,从而达到优化的效果。算法的核心步骤是:
遍历数组
a中的每个元素num。使用二分查找在
tails中找到第一个大于等于num的位置pos。如果
pos等于tails的长度,说明num比tails中所有元素都大,可以直接将num添加到tails末尾,增加子序列长度。否则,用
num替换tails[pos],以确保tails保持递增且末尾值尽可能小。
最终
tails的长度即为最长上升子序列的长度。
1 | #include<iostream> |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 coperlm's Blog!
评论
WalineDisqus

.gif)
.gif)
.gif)
.gif)
.gif)
.gif)
.gif)
.gif)
.gif)
.gif)