package main import ( "fmt" ) func max(i, j int) int { if i > j { return i } return j } func main() { num := 0 for { n, _ := fmt.Scan(&num) if n == 0 { break } else { arr := make([]int, num) for i := 0; i < num; i++ { fmt.Scan(&arr[i]) } res := f(arr) for i := 0; i < len(res); i++ { if i == len(res)-1 { fmt.Println(res[i]) } else { fmt.Printf("%d ", res[i]) } } } } } func f(arr []int) []int { end := []int{arr[0]} // end数组每个值的含义end[i],长度为i+1,对应arr所在位置的最小值 dp := make([]int, len(arr)) // 记录每个位置的长度 dp[0] = 1 // 初始时,0位置对应的长度为1,最大长度为1,所在位置为0 maxvalue := dp[0] // 递增系序列最大值 index := 0 // 递增系序列最大值所在位置 for i := 1; i < len(arr); i++ { k := find(end, arr[i]) // 在end数组中,找到大于arr[i]的第一个位置 if k == len(end) { // k右边越界,表示在当前end数组中找不到比arr[i]大的数 end = append(end, arr[i]) // 添加arr[i],表示以arr[i]结尾,最长递增子序列长度为k+1 dp[i] = k + 1 // 表示以arr[i]结尾,最长递增子序列长度为k+1 maxvalue = dp[i] index = i } else if k < len(end) && end[k] > arr[i] { // 找到1个可比较的位置,对以下2种情况合并: // 情况1: 能够找到一个位置,这个位置大于等于arr[i],只有大于大时候需要更新 // 情况2: 左边越界,此时k返回为0,这个位置要么end[k] > arr[i]进行更新,要么保留返回值 end[k] = arr[i] dp[i] = k + 1 if maxvalue == k+1 { //当递增系序列在最大长度上进行更新较小的arr[i]值,对应的位置也需要修改 index = i } } else { } } res := make([]int, maxvalue) for i, j := index, 0; i >= 0 && maxvalue != 0; i-- { // 每次按最大长度, // 每次只取最后的一个值,肯定为最小值 if dp[i] == maxvalue { maxvalue-- res[len(res)-j-1] = arr[i] j++ } } return res } // find方法,数组中的值升序,且没有重复值 // 返回值表示 // 右边越界,找不到对应的值 // 返回[0..len(end)-1] 在end数组中可以找到一个位置,这个位置>=target // 例外,返回为0时,可能表示找到,也可能表示找不到,左边越界。 func find(end []int, target int) int { l, r := 0, len(end)-1 for l <= r { mid := (r-l)/2 + l if end[mid] > target { r = mid - 1 } else if end[mid] == target { return mid } else { l = mid + 1 } } return l }