struct Solution {}
impl Solution {
    pub fn longest_obstacle_course_at_each_position(obstacles: Vec<i32>) -> Vec<i32> {
        let size = obstacles.len();

        let mut lengths: Vec<i32> = vec![1; size];
        let mut longest_increasing: Vec<i32> = vec![];

        for (i, &height) in obstacles.iter().enumerate() {
            let idx = longest_increasing.partition_point(|&x| x <= height);

            if idx == longest_increasing.len() {
                longest_increasing.push(height);
            } else {
                longest_increasing[idx] = height;
            }

            lengths[i] = (idx + 1) as i32;
        }

        lengths
    }
}

fn main() {}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn example_1() {
        assert_eq!(
            Solution::longest_obstacle_course_at_each_position(vec![1, 2, 3, 2]),
            vec![1, 2, 3, 3]
        );
    }

    #[test]
    fn example_2() {
        assert_eq!(
            Solution::longest_obstacle_course_at_each_position(vec![2, 2, 1]),
            vec![1, 2, 1]
        );
    }

    #[test]
    fn example_3() {
        assert_eq!(
            Solution::longest_obstacle_course_at_each_position(vec![3, 1, 5, 6, 4, 2]),
            vec![1, 1, 2, 3, 2, 2]
        );
    }
}