#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(); } };