Skip to content

Commit 595a438

Browse files
authored
Count rects (#81)
* saving progress * saving progress * Update mono_st.rs * saving progress * saving progress * saving progress * another assert * remove * add test * asdf * finish * better * fix * uncomment * Update mono_st.rs * Update mono_range.rs * Update mono_st.rs * fix * change style * nit * change * nits * different style * golf * consistency with c++ PTC * finish doc for mono st * simplify test * add * add docs for mono range * fix typo * nit * fix * count rects * fix clippy * beef up test * finish docs * fix doc * shorten * nit to docs * now ACs * format * nit * nits * nit * nit --------- Co-authored-by: Luke Videckis <[email protected]>
1 parent 4d18b70 commit 595a438

File tree

4 files changed

+124
-0
lines changed

4 files changed

+124
-0
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,10 @@ path = "examples/helpers/lis_pop.rs"
208208
name = "mono_st"
209209
path = "examples/monotonic/mono_st.rs"
210210

211+
[[example]]
212+
name = "count_rects"
213+
path = "examples/monotonic/count_rects.rs"
214+
211215
[[example]]
212216
name = "cartesian_tree"
213217
path = "examples/monotonic/cartesian_tree.rs"

examples/monotonic/count_rects.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// verification-helper: PROBLEM https://onlinejudge.u-aizu.ac.jp/courses/library/7/DPL/all/DPL_3_B
2+
3+
use proconio::input;
4+
use programming_team_code_rust::monotonic::count_rects::count_rects;
5+
6+
fn main() {
7+
input! {
8+
n: usize,
9+
m: usize,
10+
grid: [[u32; m]; n],
11+
}
12+
let grid = grid
13+
.iter()
14+
.map(|row| row.iter().map(|&num| num == 0).collect::<Vec<_>>())
15+
.collect::<Vec<_>>();
16+
let cnt = count_rects(&grid);
17+
18+
{
19+
let mut pref_sum = vec![vec![0; m + 1]; n + 1];
20+
for i in 0..n {
21+
for j in 0..m {
22+
pref_sum[i + 1][j + 1] =
23+
grid[i][j] as i64 + pref_sum[i + 1][j] + pref_sum[i][j + 1] - pref_sum[i][j];
24+
}
25+
}
26+
for len_i in 1..=5.min(n) {
27+
for len_j in 1..5.min(m) {
28+
let mut cnt_good_rects = 0;
29+
for i in 0..=n - len_i {
30+
for j in 0..=m - len_j {
31+
let cnt_rect = pref_sum[i + len_i][j + len_j]
32+
- pref_sum[i + len_i][j]
33+
- pref_sum[i][j + len_j]
34+
+ pref_sum[i][j];
35+
if cnt_rect == len_i as i64 * len_j as i64 {
36+
cnt_good_rects += 1;
37+
}
38+
}
39+
}
40+
assert_eq!(cnt_good_rects, cnt[len_i][len_j]);
41+
}
42+
}
43+
}
44+
45+
let mut res = 0;
46+
for (i, row) in cnt.iter().enumerate().skip(1) {
47+
for (j, &num) in row.iter().enumerate().skip(1) {
48+
if num > 0 {
49+
res = res.max(i as u64 * j as u64);
50+
}
51+
}
52+
}
53+
println!("{}", res);
54+
}

src/monotonic/count_rects.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//! # Count Rectangles
2+
3+
use crate::monotonic::mono_range::mono_range;
4+
use crate::monotonic::mono_st::mono_st;
5+
6+
/// grid is a n-by-m boolean array
7+
///
8+
/// Gets an (n+1)-by-(m+1) vec cnt where cnt\[i\]\[j\] = the number of times an i-by-j subrectangle
9+
/// appears in the grid such that all i*j cells in the subrectangle are true.
10+
///
11+
/// cnt\[i\]\[0\] and cnt\[0\]\[j\] will contain garbage numbers.
12+
///
13+
/// # Example
14+
/// ```
15+
/// use programming_team_code_rust::monotonic::count_rects::count_rects;
16+
///
17+
/// let mut cnt = count_rects(&[vec![true, true, false],
18+
/// vec![true, true, true]]);
19+
///
20+
/// // remove garbage values
21+
/// cnt.drain(0..1);
22+
/// for i in 0..cnt.len() {
23+
/// cnt[i].drain(0..1);
24+
/// }
25+
///
26+
/// assert_eq!(cnt, [[5, 3, 1],
27+
/// [2, 1, 0]]);
28+
///
29+
/// assert!(std::panic::catch_unwind(|| count_rects(&[])).is_err());
30+
/// ```
31+
///
32+
/// # Complexity
33+
/// - Time: O(nm)
34+
/// - Space: O(nm)
35+
pub fn count_rects(grid: &[Vec<bool>]) -> Vec<Vec<i32>> {
36+
let (n, m) = (grid.len(), grid[0].len());
37+
let mut cnt = vec![vec![0; m + 1]; n + 1];
38+
let mut h = vec![0; m];
39+
for row in grid {
40+
for j in 0..m {
41+
h[j] = row[j] as usize * (h[j] + 1);
42+
}
43+
let le = mono_st(&h, |x, y| x.lt(y));
44+
let ri = mono_range(&le);
45+
for j in 0..m {
46+
let (cnt_l, cnt_r) = (j - le[j].wrapping_add(1), ri[j] - j - 1);
47+
cnt[h[j]][cnt_l + cnt_r + 1] += 1;
48+
cnt[h[j]][cnt_l] -= 1;
49+
cnt[h[j]][cnt_r] -= 1;
50+
}
51+
}
52+
for row in cnt.iter_mut().skip(1) {
53+
for _ in 0..2 {
54+
for j in (1..m).rev() {
55+
row[j] += row[j + 1];
56+
}
57+
}
58+
}
59+
for i in (1..n).rev() {
60+
for j in 1..=m {
61+
cnt[i][j] += cnt[i + 1][j];
62+
}
63+
}
64+
cnt
65+
}

src/monotonic/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//! # Monotonic
22
pub mod cartesian_tree;
3+
pub mod count_rects;
34
pub mod mono_range;
45
pub mod mono_st;

0 commit comments

Comments
 (0)