#include <algorithm>
class AscentSequence {
public:
int findLongest(vector<int> A, int n) {
// write code here
//原版LIS:dp[i]代表以A[i]结尾的LIS的长度
//优化版本:使用二分查找加贪心,dp[i]代表所有长度为i+1的上升子序列中最小的末尾元素值。例如dp[2]代表所有长度为3的上升子序列中末尾元素的最小值。
//遍历数组nums[i],每次在dp中查找第一个出现的大于等于nums[i]的位置,将其替换成nums[i];如果不存在这样的位置,则将nums[i]插入dp的末尾。dp是严格递增序列,由其性质或者反证法可知;
//充分性:假设处理nums[i]时,在dp中找到了dp[j]第一个大于等于nums[i],那么dp[j-1]小于nums[i],说明nums[i]可以添加到dp[j-1]元素所代表的递增子序列的末尾使得序列长度加一,也就对应着dp[j]的位置。
//必要性:由于dp严格递增,那么每次nums[i]必须且只能更新dp中的一个位置。如果更新两个以上的位置则无法满足严格递增
vector<int>dp;
for(int i=0; i<n; i++)
{
//在dp中找到第一个大于等于A[i]的位置
auto it=lower_bound(dp.begin(), dp.end(), A[i]);
if(it!=dp.end())
*it=A[i];
else
dp.push_back(A[i]);
}
return dp.size();
}
};