29 信封嵌套问题
Table of Contents

ac

转化为最长递增子序列问题,不过需要绝对递增(等于要处理好)

import java.util.Arrays;
import java.util.Scanner;


class Ev{
    public int l;
    public int w;
}

public class Main {

    public static Scanner sc = new Scanner(System.in);

    public static void main(String[] args) {
        int n = sc.nextInt();
        Ev[] arr = new Ev[n];
        for(int i = 0; i < n; i ++){
            arr[i] = new Ev();
            arr[i].l = sc.nextInt();
            arr[i].w = sc.nextInt();
        }
        Arrays.sort(arr, (a, b)->{
            if(a.l < b.l){
                return -1;
            }else if(a.l == b.l){
                if(a.w < b.w){
                    return -1;
                }else if(a.w == b.w){
                    return 0;
                }
            }
            return 1;
        });
        int[] newArr = new int[n];
        for(int i=0;i<n;i++){
            newArr[i] = arr[i].w;
        }
        int ans = getMax(newArr, n);
        System.out.println(ans);
    }

    // 最左边大于等于val的数
    static int bsearch(int[] ends, int left, int right, int val){
        if(val <= ends[left]){
            return -2;
        }
        if(val > ends[right]){
            return -1;
        }
        if(val == ends[right]){
            return -3;
        }
        while (left <= right){
            int mid = (left + right) / 2;
            if(ends[mid] <= val){
                left = mid + 1;
            }else {
                right = mid - 1;
            }
        }
        return left;
    }

    static int getMax(int[] arr, int n){
        // ends[b] = c 表示遍历到目前为止 长度为b+1的递增序列中,最小的结尾数 c
        // ends[] 是一个递增的数组,适合二分法
        int[] ends = new int[n];
        // dp[i] 以 i 位置结束的最长递增长度
        int[] dp = new int[n];
        dp[0] = 1;
        ends[0] = arr[0];
        // 有效区域[0, right]; right + 1 为 最长递增
        int right = 0;
        for(int i=1;i<n;i++){
            int pos = bsearch(ends,0, right, arr[i]);
            if(pos == -1){ //  arr[i] 当前最大
                right = right + 1;
                ends[right] = arr[i];
                dp[i] = right + 1;
            }else if(pos == -2){
                ends[0] = arr[i];
                dp[i] = 1;
            }else if(pos == -3){
                dp[i] = right;
            }else{
                right = Math.max(right, pos);
                ends[pos] = arr[i];
                dp[i] = pos + 1;
            }
        }
        int maxLen = right + 1;
        return maxLen;
    }

}
/*
9
3 4
2 3
4 5
1 3
2 2
3 6
1 2
3 2
2 4

4
*/

超时

import java.util.Arrays;
import java.util.Scanner;


class Ev{
    public int l;
    public int w;
}

public class Main {

    public static Scanner sc = new Scanner(System.in);

    public static void main(String[] args) {
        int n = sc.nextInt();
        Ev[] arr = new Ev[n];
        for(int i = 0; i < n; i ++){
            arr[i] = new Ev();
            arr[i].l = sc.nextInt();
            arr[i].w = sc.nextInt();
        }
        Arrays.sort(arr, (a, b)->{
            if(a.l < b.l){
                return -1;
            }else if(a.l == b.l){
                if(a.w < b.w){
                    return -1;
                }else if(a.w == b.w){
                    return 0;
                }
            }
            return 1;
        });
        int[] dpPre = new int[n];
        int[] dp = new int[n];
        for(int i=0;i<n;i++){
            dp[i] = 1;
            dpPre[i] = -1;
        }
        int ans = 0;
        for(int i=1;i<n;i++){
            for(int j=0;j<i;j++){
                if(arr[j].l < arr[i].l && arr[j].w < arr[i].w){
                    if(dp[j] + 1 > dp[i]) {
                        dp[i] =  dp[j] + 1;
                        dpPre[i] = j;
                    }
                    if(dp[i] > ans){
                        ans = dp[i];
                    }
                }
            }
        }
        System.out.println(ans);
    }

}
/*
9
3 4
2 3
4 5
1 3
2 2
3 6
1 2
3 2
2 4

4
*/