Rust memoization
Approach\n1. Convert first_player and second_player to i and j, which are 0-based and i < j.\n\n2. When a player (let\'s say a) other than i and j advances to n
# Approach\n1. Convert `first_player` and `second_player` to `i` and `j`, which are 0-based and `i < j`.\n\n2. When a player (let\'s say `a`) other than `i` and `j` advances to next round, there are 3 cases to consider regarding to `a`\'s position:\n- Region 0 (left -> l): `a < i`.\n- Region 1 (middle -> m): `i < a < j`.\n- Region 2 (right -> r): `j < a`.\n```\n[...i...j...]\n  \u2191   \u2191   \u2191\n  0   1   2\n```\n\n3. Considering that when two players compete, there can be different cases of what region the winner can fall into after each match. Some variables (`l`, `m`, `lr`, `lm`, `mr`) are used here to count each possibility. (There is no `r` simply because it is not needed for calculation in step 4.)\n\n4. Use those variables (`l`, `m`, `lr`, `lm`, `mr`) to **iterate through all possibilities** of what **new indices** `i` and `j` can fall into in the next round.\n\n4. Add top-down DP logic to get the answer using the memoized answers of next round.\n# Code\n```\nimpl Solution {\n    pub fn earliest_and_latest(n: i32, first_player: i32, second_player: i32) -> Vec<i32> {\n        let n = n as usize;\n        let i = first_player as usize - 1;\n        let j = second_player as usize - 1;;\n        let mut dp = vec![vec![vec![vec![-1; 2]; j + 1]; i + 1]; n + 1];\n        Self::memo(n, i, j, &mut dp);\n        dp[n][i].pop().unwrap()\n    }\n\n    fn memo(n: usize, i: usize, j: usize, dp: &mut Vec<Vec<Vec<Vec<i32>>>>) {\n        if dp[n][i][j][0] != -1 {\n            return;\n        }\n        if i + j + 1 == n {\n            dp[n][i][j][0] = 1;\n            dp[n][i][j][1] = 1;\n            return;\n        }\n        let n2 = (n + 1) / 2;\n        let i_seq = i.min(n - i - 1);\n        let j_seq = j.min(n - j - 1);\n        let mut l = 0;\n        let mut m = 0;\n        let mut lr = 0;\n        let mut lm = 0;\n        let mut mr = 0;\n        for a in 0..n2 {\n            if a == i_seq || a == j_seq {\n                continue;\n            }\n            let b = n - a - 1;\n            match (Self::get_region(a, i, j), Self::get_region(b, i, j)) {\n                (0, 0) => l += 1,\n                (0, 1) => lm += 1,\n                (0, 2) => lr += 1,\n                (1, 1) => m += 1,\n                (1, 2) => mr += 1,\n                (2, 2) => (),\n                _ => unreachable!(),\n            }\n        }\n        dp[n][i][j][0] = i32::MAX;\n        dp[n][i][j][1] = i32::MIN;\n        for lr_i in 0..=lr {\n            for lm_i in 0..=lm {\n                for mr_i in 0..=mr {\n                    let i2 = l + lr_i + lm_i;\n                    let j2 = l + m + lr_i + lm + mr_i + 1;\n                    Self::memo(n2, i2, j2, dp);\n                    dp[n][i][j][0] = dp[n][i][j][0].min(dp[n2][i2][j2][0] + 1);\n                    dp[n][i][j][1] = dp[n][i][j][1].max(dp[n2][i2][j2][1] + 1);\n                }\n            }\n        }\n    }\n\n    fn get_region(a: usize, i: usize, j: usize) -> i32 {\n        if a < i { 0 } else if a < j { 1 } else { 2 }\n    }\n}\n```
['Dynamic Programming', 'Memoization', 'Rust']