haar_lib/algo/
max_rect.rs1use crate::chmax;
3use std::{
4 cmp::Ordering,
5 ops::{Mul, Range},
6};
7
8pub fn max_rect_in_histogram<T>(h: &[T]) -> (T, Range<usize>)
12where
13 T: From<usize> + Mul<Output = T> + Ord + Copy,
14{
15 let mut st: Vec<(T, usize)> = vec![];
16 let mut ret = T::from(0);
17 let mut lr = (0, 0);
18
19 for (i, &y1) in h.iter().enumerate() {
20 if let Some(&(y2, _)) = st.last() {
21 match y2.cmp(&y1) {
22 Ordering::Less => {
23 st.push((y1, i));
24 }
25 Ordering::Greater => {
26 let mut j = i;
27 while let Some(&(y3, k)) = st.last() {
28 if y3 <= y1 {
29 break;
30 }
31 if chmax!(ret, y3 * T::from(i - k)) {
32 lr = (k, i);
33 }
34 j = k;
35 st.pop();
36 }
37 st.push((y1, j));
38 }
39 _ => {}
40 };
41 } else {
42 st.push((y1, i));
43 }
44 }
45
46 while let Some((y, i)) = st.pop() {
47 if chmax!(ret, y * T::from(h.len() - i)) {
48 lr = (i, h.len());
49 }
50 }
51
52 (
53 ret,
54 Range {
55 start: lr.0,
56 end: lr.1,
57 },
58 )
59}
60
61pub fn max_rect<T: Copy + PartialEq>(d: &[Vec<T>], value: T) -> usize {
65 let h = d.len();
66 let w = d[0].len();
67
68 let mut c = vec![vec![0; w]; h];
69 for i in 0..h {
70 for j in 0..w {
71 if d[i][j] == value {
72 c[i][j] = 1;
73 }
74 }
75 }
76
77 for i in 1..h {
78 for j in 0..w {
79 if c[i][j] == 1 {
80 c[i][j] += c[i - 1][j];
81 }
82 }
83 }
84
85 c.into_iter()
86 .map(|s| max_rect_in_histogram(&s).0)
87 .max()
88 .unwrap()
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 #[test]
96 fn test_histogram() {
97 let a = [2, 1, 3, 5, 3, 4, 2, 1];
100 let (ans, Range { start: l, end: r }) = max_rect_in_histogram(&a);
101 assert_eq!(ans, 12);
102 assert_eq!(ans, a[l..r].iter().min().unwrap() * (r - l));
103
104 let a = [2, 0, 1];
105 let (ans, Range { start: l, end: r }) = max_rect_in_histogram(&a);
106 assert_eq!(ans, 2);
107 assert_eq!(ans, a[l..r].iter().min().unwrap() * (r - l));
108 }
109
110 #[test]
111 fn test_max_rect() {
112 assert_eq!(
114 max_rect(
115 &[
116 vec![0, 0, 1, 0, 0],
117 vec![1, 0, 0, 0, 0],
118 vec![0, 0, 0, 1, 0],
119 vec![0, 0, 0, 1, 0]
120 ],
121 0
122 ),
123 6
124 );
125 }
126}