//1.理解贪心算法使用
//2.maxLen数组的作用--找到字典序递增子序列
//3.二分查找
//Leetcode上最长递增子序列求长度+牛佬“华科不平凡”的maxLen数组恢复字典序

class Solution {
public:
    //找到第一个比value大的值
    int binarySearch(vector<int>&res,int value){
        int left=0;
        int right=res.size()-1;

        //如果没找到就返回位置0,因为这时res的值全部大于value,需要替换第一个
        int pos=0;
        while(left<=right){
            int middle=left+((right-left)>>1);

            if(res[middle]>value){
                pos=middle;
                right=middle-1;
            }
            else{
                left=middle+1;
            }   
        }
        //没找到就返回pos==0
        return pos;

    }

    vector<int> LIS(vector<int>& arr) {
        if(arr.empty()) return {};

        vector<int> res;               //存放递增子序列
        vector<int> maxLen;            //存放当前元素在子序列最后一位时子序列长度

        res.emplace_back(arr[0]);
        maxLen.emplace_back(1);

        for(int i=1;i<arr.size();i++){
            if(arr[i]>res.back()){
                res.emplace_back(arr[i]);
                maxLen.emplace_back(res.size());
            }else{
                int pos=binarySearch(res,arr[i]);
                res[pos]=arr[i];
                maxLen.emplace_back(pos+1);

            }

        }
        //从后往前更新最长递增子序列
        for(int i=arr.size()-1,j=res.size();j>0;--i){
            if(maxLen[i]==j){
                res[--j]=arr[i];
            }    
        }

        return res;

    }
}