There are several squares being dropped onto the X-axis of a 2D plane.
You are given a 2D integer array positions where positions[i] = [lefti, sideLengthi] represents the ith square with a side length of sideLengthi that is dropped with its left edge aligned with X-coordinate lefti.
Each square is dropped one at a time from a height above any landed squares. It then falls downward (negative Y direction) until it either lands on the top side of another square or on the X-axis. A square brushing the left/right side of another square does not count as landing on it. Once it lands, it freezes in place and cannot be moved.
After each square is dropped, you must record the height of the current tallest stack of squares.
Return an integer array ans where ans[i] represents the height described above after dropping the ith square.
Example 1:

Input: positions = [[1,2],[2,3],[6,1]]
Output: [2,5,5]
Explanation:
After the first drop, the tallest stack is square 1 with a height of 2.
After the second drop, the tallest stack is squares 1 and 2 with a height of 5.
After the third drop, the tallest stack is still squares 1 and 2 with a height of 5.
Thus, we return an answer of [2, 5, 5].
Example 2:
Input: positions = [[100,100],[200,100]]
Output: [100,100]
Explanation:
After the first drop, the tallest stack is square 1 with a height of 100.
After the second drop, the tallest stack is either square 1 or square 2, both with heights of 100.
Thus, we return an answer of [100, 100].
Note that square 2 only brushes the right side of square 1, which does not count as landing on it.
Constraints:
- 1 <= positions.length <= 1000
- 1 <= lefti <= 108
- 1 <= sideLengthi <= 106
用 coordinate compression 和 segment tree 来解
use std::collections::{HashMap, HashSet};
struct SegmentTree {
n: usize,
heights: Vec<i32>,
}
impl SegmentTree {
fn new(n: usize) -> Self {
let mut curr = 1;
let mut total = 1;
while curr < n {
curr *= 2;
total += curr;
}
Self { n: curr, heights: vec![0; total] }
}
fn query(&mut self, i: usize, left: usize, right: usize, start: usize, end: usize) -> i32 {
if start >= right || end < left {
return 0;
}
if start <= left && end > right - 1 {
return self.heights[i];
}
if left == right - 1 {
return 0;
}
let left_height = self.query(i * 2 + 1, left, (left + right) / 2, start, end);
let right_height = self.query(i * 2 + 2, (left + right) / 2, right, start, end);
return left_height.max(right_height);
}
fn update(&mut self, i: usize, left: usize, right: usize, start: usize, end: usize, height: i32) {
if start >= right || end < left {
return;
}
if start <= left && end > right - 1 {
self.heights[i] = height;
}
if left == right - 1 {
return;
}
self.update(i * 2 + 1, left, (left + right) / 2, start, end, height);
self.update(i * 2 + 2, (left + right) / 2, right, start, end, height);
self.heights[i] = self.heights[i * 2 + 1].max(self.heights[i * 2 + 2]);
}
}
impl Solution {
fn compress_coordinates(positions: &Vec<Vec<i32>>) -> HashMap<i32, usize> {
let set: HashSet<i32> = positions.iter().map(|v| vec![v[0], v[0] + v[1]]).flatten().collect();
let mut l: Vec<i32> = set.into_iter().collect();
l.sort();
l.into_iter().enumerate().fold(HashMap::new(), |mut m, (i, v)| {
m.entry(v).or_insert(i);
m
})
}
pub fn falling_squares(positions: Vec<Vec<i32>>) -> Vec<i32> {
let coords = Solution::compress_coordinates(&positions);
let mut tree = SegmentTree::new(coords.len());
let mut ans = Vec::new();
let mut highest = 0;
for p in positions {
let start = *coords.get(&(p[0])).unwrap();
let end = *coords.get(&(p[0] + p[1])).unwrap();
let height = tree.query(0, 0, tree.n, start, end) + p[1];
tree.update(0, 0, tree.n, start, end, height);
highest = highest.max(height);
ans.push(highest);
}
ans
}
}

这篇博客详细介绍了LeetCode中的一道题目——Falling Squares。通过给出的示例和约束条件,解释了如何使用坐标压缩和线段树的数据结构来解决这道动态规划问题,旨在帮助读者理解解题思路和算法应用。
1725

被折叠的 条评论
为什么被折叠?



