import java.util.*;


public class Solution {
    /**
     * retrun the longest increasing subsequence
     * @param arr int整型一维数组 the array
     * @return int整型一维数组
     */
    //思路:
    /*
    1.维护一个临时数组tmp,这里面存储当前的最长上升子序列;
    2.遍历arr中的元素,不断的将当前元素加入tmp,或者替换tmp中的元素,使得tmp保持上升;
        2.1 对于arr[i] ,若其大于tmp的最后一个元素,那么直接将其加入到tmp的末尾,
        2.2 对于arr[i],若其小于tmp的最后一个元素,则在tmp从左到右中找到第一个比奇大的元素并替换他
    3.每次处理完一个arr[i],都将arr[i]加入到或者替换到tmp的位置记录到pos中,如pos[i]表示arr[i]在tmp中的位置
    4.整过程中,tmp的长度都是不减的,因此,最后tmp的长度就是最长上上升子序列的长度,从tmp的最后一个元素开始向前遍历(s从后往前是为了
    保证,结果是按字典序取最小的要求,这一点你们自己思考吧,不难),在pos中寻找位置为tmp中对应位置的pos[i],将arr[i]记录到结果数组中即可。
    */
    public int[] LIS (int[] arr) {
        if(arr == null || arr.length == 0) return arr ;
        //tmp[i]表示 当前最长上升子序列 i位置的 元素
        int tmp[] = new int[arr.length] ;
        //pos[i]表示 将arr[i]加入当前最长上升子序列中 时arr[i]应该在序列中的 位置
        int pos[] =  new int[arr.length] ;
        tmp[0] = arr[0] ;
        pos[0] = 0 ;
        int tmpIndex = 0 ;//当前最长上升子序列的最后一元素的 位置
        for(int i = 1 ; i < arr.length ; i ++) {
            if(arr[i] > tmp[tmpIndex]) {
                tmp[++ tmpIndex] = arr[i] ;
                pos[i] = tmpIndex ;
            } else if(arr[i] == tmp[tmpIndex]) {
                pos[i] = tmpIndex ;
            } else {
                //二分查找位置
                int findIdx = findPos(tmp , tmpIndex , arr[i]) ;
                tmp[findIdx] = arr[i] ;
                pos[i] = findIdx ;
            }
        }
        int res[] = new int[tmpIndex + 1] ;
        for(int j = tmpIndex , i = arr.length - 1 ; j >= 0 ; i --) { 
            if(pos[i] == j) {
                res[j --] = arr[i] ;
            }
        }
        return res ;
        
    }
    //在tmp中 查找第一个比target大的数
    public int findPos(int tmp[] , int end , int target) {
        int i = 0 ;
        int j = end ;
        while(i <= j) {
            int mid = i + (j - i) / 2 ;
            if(target > tmp[mid]) {
                i = mid + 1 ;
            } else {
                j = mid - 1 ;
            }
        }
        return i ;
    }
}