介绍
最长上升子序列问题,也就是Longest increasing subsequence,缩写为LIS。是指在一个序列中求长度最长的一个上升子序列的问题,是动态规划中一个相当经典问题。在这里我们可以看到,这个上升实质上就是一个对<进行定义的过程,所以我们求解的其实是一类问题,也就是在给定序列中求解长度最长的符合某一性质的子序列的问题。
解法一
状态设计:F[i]代表以A[i]结尾的LIS的长度
状态转移:F[i]=max{F[j]+1}(1<=j< i,A[j]< A[i])
边界处理:F[i]=1(1<=i<=n)
时间复杂度:O(n^2)
PS(理解dp最简单的方法:画表,自行推理)
1 | #include<bits/stdc++.h> |
解法二
贪心加二分
1 | #include<bits/stdc++.h> |
解法三
用树状数组维护,降低复杂度。
PS(我写完后发现这个方法将相等的也计算在其中)。
不知道有没有人能去除掉相等,是我太菜了,QWQ.
维护每个数的序列也就是第几个数,然后查询其前面的最长上升子序列,然后更新其后的值。
1 | #include<bits/stdc++.h> |
解法四
随后我查了相关的博客后,发现换个思维就可以排除相等的情况。
即维护每一个刚输入的值,查询其前面的最长的上升子序列。
1 | #include<bits/stdc++.h> |
不过解法三和四都有一定的局限性,只能所有数都是>=1的正整数时才能用,不过这种思维可以用在好多地方。
如果存在负数的情况,用方法二是最好的。