Skip to content

Commit 09f29e8

Browse files
committed
Add problem 850: Rectangle Area II
1 parent 9731eca commit 09f29e8

File tree

3 files changed

+349
-0
lines changed

3 files changed

+349
-0
lines changed

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,7 @@ pub mod problem_0846_hand_of_straights;
702702
pub mod problem_0847_shortest_path_visiting_all_nodes;
703703
pub mod problem_0848_shifting_letters;
704704
pub mod problem_0849_maximize_distance_to_closest_person;
705+
pub mod problem_0850_rectangle_area_ii;
705706
pub mod problem_0851_loud_and_rich;
706707
pub mod problem_0852_peak_index_in_a_mountain_array;
707708
pub mod problem_0853_car_fleet;
+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
pub mod sweep_line_with_segment_tree;
2+
3+
pub trait Solution {
4+
fn rectangle_area(rectangles: Vec<Vec<i32>>) -> i32;
5+
}
6+
7+
#[cfg(test)]
8+
mod tests {
9+
use super::Solution;
10+
use crate::test_utilities::Matrix;
11+
12+
pub fn run<S: Solution>() {
13+
let test_cases = [
14+
(&[[0, 0, 2, 2], [1, 0, 2, 3], [1, 0, 3, 1]] as &dyn Matrix<_>, 6),
15+
(&[[0, 0, 1_000_000_000, 1_000_000_000]], 49),
16+
(&[[25, 20, 70, 27], [68, 80, 79, 100], [37, 41, 66, 76]], 1550),
17+
(&[[49, 40, 62, 100], [11, 83, 31, 99], [19, 39, 30, 99]], 1584),
18+
(&[[39, 99, 60, 100], [69, 14, 91, 56], [13, 42, 20, 70]], 1141),
19+
(
20+
&[
21+
[93516, 44895, 94753, 69358],
22+
[13141, 52454, 59740, 71232],
23+
[22877, 11159, 85255, 61703],
24+
[11917, 8218, 84490, 36637],
25+
[75914, 29447, 83941, 64384],
26+
[22490, 71433, 64258, 74059],
27+
[18433, 51177, 87595, 98688],
28+
[70854, 80720, 91838, 92304],
29+
[46522, 49839, 48550, 94096],
30+
[95435, 37993, 99139, 49382],
31+
[10618, 696, 33239, 45957],
32+
[18854, 2818, 57522, 78807],
33+
[61229, 36593, 76550, 41271],
34+
[99381, 90692, 99820, 95125],
35+
],
36+
971_243_962,
37+
),
38+
(&[[71, 73, 72, 84], [56, 60, 64, 64], [82, 8, 85, 95]], 304),
39+
];
40+
41+
for (rectangles, expected) in test_cases {
42+
assert_eq!(S::rectangle_area(rectangles.to_vec()), expected);
43+
}
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
pub struct Solution;
2+
3+
// ------------------------------------------------------ snip ------------------------------------------------------ //
4+
5+
// See <https://en.wikipedia.org/wiki/Klee%27s_measure_problem>.
6+
7+
use std::cmp::Ordering;
8+
use std::collections::{HashMap, HashSet};
9+
use std::convert::TryInto;
10+
11+
struct Node {
12+
count: u32,
13+
covered: u32,
14+
}
15+
16+
struct Tree<'a> {
17+
root: &'a mut Node,
18+
left: &'a mut [Node],
19+
right: &'a mut [Node],
20+
start: u32,
21+
length: u32,
22+
}
23+
24+
impl<'a> Tree<'a> {
25+
fn from_slice(slice: &'a mut [Node], start: u32) -> Self {
26+
let length = (slice.len() + 1) / 2;
27+
let (root, children) = slice.split_first_mut().unwrap();
28+
let left_length = length / 2;
29+
let (left, right) = children.split_at_mut((left_length * 2).saturating_sub(1));
30+
31+
Self {
32+
root,
33+
left,
34+
right,
35+
start,
36+
length: length as _,
37+
}
38+
}
39+
40+
fn as_non_leaf_tree(&mut self) -> NonLeafTree {
41+
let left_length = self.length / 2;
42+
43+
NonLeafTree {
44+
root: self.root,
45+
left: Tree::from_slice(self.left, self.start),
46+
right: Tree::from_slice(self.right, self.start + left_length),
47+
start: self.start,
48+
length: self.length,
49+
}
50+
}
51+
52+
fn end(&self) -> u32 {
53+
self.start + self.length
54+
}
55+
}
56+
57+
struct NonLeafTree<'a> {
58+
root: &'a mut Node,
59+
left: Tree<'a>,
60+
right: Tree<'a>,
61+
start: u32,
62+
length: u32,
63+
}
64+
65+
impl NonLeafTree<'_> {
66+
fn middle(&self) -> u32 {
67+
self.start + self.length / 2
68+
}
69+
}
70+
71+
impl Solution {
72+
fn segment_tree_insert(tree: &mut Tree, ys: &[u32], start: u32, end: u32) {
73+
fn insert_left_aligned(mut tree: NonLeafTree, ys: &[u32], start: u32, end: u32) {
74+
let middle = tree.middle();
75+
76+
if end < middle {
77+
insert_left_aligned(tree.left.as_non_leaf_tree(), ys, start, end);
78+
} else {
79+
insert_aligned(tree.left.root, ys, start, middle);
80+
81+
if end > middle {
82+
insert_left_aligned(tree.right.as_non_leaf_tree(), ys, middle, end);
83+
}
84+
}
85+
86+
if tree.root.count == 0 {
87+
tree.root.covered = tree.left.root.covered + tree.right.root.covered;
88+
}
89+
}
90+
91+
fn insert_right_aligned(mut tree: NonLeafTree, ys: &[u32], start: u32, end: u32) {
92+
let middle = tree.middle();
93+
94+
if start > middle {
95+
insert_right_aligned(tree.right.as_non_leaf_tree(), ys, start, end);
96+
} else {
97+
insert_aligned(tree.right.root, ys, middle, end);
98+
99+
if start < middle {
100+
insert_right_aligned(tree.left.as_non_leaf_tree(), ys, start, middle);
101+
}
102+
}
103+
104+
if tree.root.count == 0 {
105+
tree.root.covered = tree.left.root.covered + tree.right.root.covered;
106+
}
107+
}
108+
109+
fn insert_not_aligned(mut tree: NonLeafTree, ys: &[u32], start: u32, end: u32) {
110+
let middle = tree.middle();
111+
112+
match start.cmp(&middle) {
113+
Ordering::Less => match end.cmp(&middle) {
114+
Ordering::Less => insert_not_aligned(tree.left.as_non_leaf_tree(), ys, start, end),
115+
Ordering::Equal => insert_right_aligned(tree.left.as_non_leaf_tree(), ys, start, end),
116+
Ordering::Greater => {
117+
insert_right_aligned(tree.left.as_non_leaf_tree(), ys, start, middle);
118+
insert_left_aligned(tree.right.as_non_leaf_tree(), ys, middle, end);
119+
}
120+
},
121+
Ordering::Equal => insert_left_aligned(tree.right.as_non_leaf_tree(), ys, start, end),
122+
Ordering::Greater => insert_not_aligned(tree.right.as_non_leaf_tree(), ys, start, end),
123+
}
124+
125+
if tree.root.count == 0 {
126+
tree.root.covered = tree.left.root.covered + tree.right.root.covered;
127+
}
128+
}
129+
130+
fn insert_aligned(root: &mut Node, ys: &[u32], start: u32, end: u32) {
131+
if root.count == 0 {
132+
root.covered = ys[end as usize] - ys[start as usize];
133+
}
134+
135+
root.count += 1;
136+
}
137+
138+
if start == tree.start {
139+
if end == tree.end() {
140+
insert_aligned(tree.root, ys, start, end);
141+
} else {
142+
insert_left_aligned(tree.as_non_leaf_tree(), ys, start, end);
143+
}
144+
} else if end == tree.end() {
145+
insert_right_aligned(tree.as_non_leaf_tree(), ys, start, end);
146+
} else {
147+
insert_not_aligned(tree.as_non_leaf_tree(), ys, start, end);
148+
}
149+
}
150+
151+
fn segment_tree_remove(tree: &mut Tree, ys: &[u32], start: u32, end: u32) {
152+
fn remove_left_aligned(mut tree: NonLeafTree, ys: &[u32], start: u32, end: u32) {
153+
let middle = tree.middle();
154+
155+
if end < middle {
156+
remove_left_aligned(tree.left.as_non_leaf_tree(), ys, start, end);
157+
} else {
158+
remove_aligned(&mut tree.left);
159+
160+
if end > middle {
161+
remove_left_aligned(tree.right.as_non_leaf_tree(), ys, middle, end);
162+
}
163+
}
164+
165+
if tree.root.count == 0 {
166+
tree.root.covered = tree.left.root.covered + tree.right.root.covered;
167+
}
168+
}
169+
170+
fn remove_right_aligned(mut tree: NonLeafTree, ys: &[u32], start: u32, end: u32) {
171+
let middle = tree.middle();
172+
173+
if start > middle {
174+
remove_right_aligned(tree.right.as_non_leaf_tree(), ys, start, end);
175+
} else {
176+
remove_aligned(&mut tree.right);
177+
178+
if start < middle {
179+
remove_right_aligned(tree.left.as_non_leaf_tree(), ys, start, middle);
180+
}
181+
}
182+
183+
if tree.root.count == 0 {
184+
tree.root.covered = tree.left.root.covered + tree.right.root.covered;
185+
}
186+
}
187+
188+
fn remove_not_aligned(mut tree: NonLeafTree, ys: &[u32], start: u32, end: u32) {
189+
let middle = tree.middle();
190+
191+
match start.cmp(&middle) {
192+
Ordering::Less => match end.cmp(&middle) {
193+
Ordering::Less => remove_not_aligned(tree.left.as_non_leaf_tree(), ys, start, end),
194+
Ordering::Equal => remove_right_aligned(tree.left.as_non_leaf_tree(), ys, start, end),
195+
Ordering::Greater => {
196+
remove_right_aligned(tree.left.as_non_leaf_tree(), ys, start, middle);
197+
remove_left_aligned(tree.right.as_non_leaf_tree(), ys, middle, end);
198+
}
199+
},
200+
Ordering::Equal => remove_left_aligned(tree.right.as_non_leaf_tree(), ys, start, end),
201+
Ordering::Greater => remove_not_aligned(tree.right.as_non_leaf_tree(), ys, start, end),
202+
}
203+
204+
if tree.root.count == 0 {
205+
tree.root.covered = tree.left.root.covered + tree.right.root.covered;
206+
}
207+
}
208+
209+
fn remove_aligned(mut tree: &mut Tree) {
210+
tree.root.count -= 1;
211+
212+
if tree.root.count == 0 {
213+
tree.root.covered = if let (Some(left), Some(right)) = (tree.left.first(), tree.right.first()) {
214+
left.covered + right.covered
215+
} else {
216+
0
217+
};
218+
}
219+
}
220+
221+
if start == tree.start {
222+
if end == tree.end() {
223+
remove_aligned(tree);
224+
} else {
225+
remove_left_aligned(tree.as_non_leaf_tree(), ys, start, end);
226+
}
227+
} else if end == tree.end() {
228+
remove_right_aligned(tree.as_non_leaf_tree(), ys, start, end);
229+
} else {
230+
remove_not_aligned(tree.as_non_leaf_tree(), ys, start, end);
231+
}
232+
}
233+
234+
pub fn rectangle_area(rectangles: Vec<Vec<i32>>) -> i32 {
235+
// Build events and compress y coordinates.
236+
237+
let mut events = Vec::with_capacity(rectangles.len() * 2);
238+
let mut ys = HashSet::new();
239+
240+
for rectangle in &rectangles {
241+
let [x_1, y_1, x_2, y_2]: [_; 4] = rectangle.as_slice().try_into().unwrap();
242+
let (x_1, y_1, x_2, y_2) = (x_1 as u32, y_1 as u32, x_2 as u32, y_2 as u32);
243+
244+
ys.extend(&[y_1, y_2]);
245+
246+
events.push((x_1, y_1, y_2));
247+
events.push((x_2, y_1 | 0x8000_0000, y_2));
248+
}
249+
250+
let mut ys = ys.into_iter().collect::<Vec<_>>();
251+
252+
ys.sort_unstable();
253+
254+
let y_map = ys.iter().copied().zip(0..).collect::<HashMap<_, _>>();
255+
256+
events.sort_unstable_by_key(|&(x, _, _)| x);
257+
258+
// Build segment tree.
259+
260+
let mut nodes = (0..ys.len() * 2 - 3)
261+
.map(|_| Node { count: 0, covered: 0 })
262+
.collect::<Vec<_>>();
263+
264+
let mut tree = Tree::from_slice(&mut nodes, 0);
265+
266+
// Run events and calculate result.
267+
268+
let mut result = 0;
269+
let mut prev_x = 0;
270+
271+
for &(x, y_1, y_2) in &events {
272+
if x != prev_x {
273+
result += u64::from(tree.root.covered) * u64::from(x - prev_x);
274+
275+
prev_x = x;
276+
}
277+
278+
if y_1 & 0x8000_0000 == 0 {
279+
Self::segment_tree_insert(&mut tree, &ys, y_map[&y_1], y_map[&y_2]);
280+
} else {
281+
Self::segment_tree_remove(&mut tree, &ys, y_map[&(y_1 & 0x7FFF_FFFF)], y_map[&y_2]);
282+
}
283+
}
284+
285+
(result % 1_000_000_007) as _
286+
}
287+
}
288+
289+
// ------------------------------------------------------ snip ------------------------------------------------------ //
290+
291+
impl super::Solution for Solution {
292+
fn rectangle_area(rectangles: Vec<Vec<i32>>) -> i32 {
293+
Self::rectangle_area(rectangles)
294+
}
295+
}
296+
297+
#[cfg(test)]
298+
mod tests {
299+
#[test]
300+
fn test_solution() {
301+
super::super::tests::run::<super::Solution>();
302+
}
303+
}

0 commit comments

Comments
 (0)