nekolib/ds/disjoint_sparse_table.rs
1//! disjoint sparse table。
2
3use super::super::traits::binop;
4use super::super::traits::fold;
5use super::super::utils::buf_range;
6
7use std::convert::From;
8use std::ops::{Index, Range, RangeBounds};
9
10use binop::Monoid;
11use buf_range::bounds_within;
12use fold::Fold;
13
14/// disjoint sparse table。
15///
16/// 要素数 $n$ の配列の任意の区間について、モノイド積の値を計算できる。
17/// 値の更新はできない。
18/// 半群を返すことにしてもよいが、要検討。
19///
20/// # Idea
21/// 各 $k$ ($1\\le k\< \\log\_2(n)$) について、区間
22/// $[i\\cdot 2\^k-j, i\\cdot 2\^k)$ および $[i\\cdot 2\^k, i\\cdot 2\^k+j)$
23/// ($2\\le j\\le 2\^k$、$i$ は区間の終端が $n$ 以下になる各奇数)
24/// におけるモノイド積を予め計算しておく。
25/// 任意の区間は、上記の区間を高々 $2$ つ合わせることで表現できる。
26///
27/// # Implementation notes
28/// 前処理では、異なる段で同じ区間のモノイド積を複数回計算するのを避けるための工夫をしている。
29/// その処理のオーバーヘッドにより、モノイド積のコストが高くない場合は、
30/// 毎回計算する方が高速かもしれない。クエリ処理についても同様の工夫をしている。
31///
32/// # Complexity
33/// |演算|時間計算量|
34/// |---|---|
35/// |`from`|$\\Theta(n\\log(n))$|
36/// |`fold`|$\\Theta(1)$|
37///
38/// # Precise analysis
39/// 前処理におけるモノイド積の計算回数は以下の値で上から抑えられる。
40/// $$ n\\cdot\\lceil{\\log\_2(n)-3}\\rceil + 2\\cdot\\lceil{\\log\_2(n)}\\rceil + 2. $$
41///
42/// これは、$n = 1000$ で $7022$ であり、
43/// [Secret](http://s3-ap-northeast-1.amazonaws.com/data.cms.ioi-jp.org/open-2014/2014-open-d2-secret.pdf)
44/// の「$n = 1000$ でクエリ $8000$ 回以下」に余裕を持って間に合う。
45///
46/// クエリ処理の際には、
47/// 与えられた区間が前処理で計算した区間であるか、長さが $1$ 以下の場合は、
48/// 新たにモノイド積は計算せずに答えを返す。
49/// そうでない場合はちょうど $1$ 回のモノイド積を計算する。
50///
51/// ## More precise analysis
52///
53/// 前処理の実際の計算回数は、以下のコードにより $O(\\log(n))$ 時間で計算できるはず。
54/// コード長が長いので隔離したいかも。
55/// ```
56/// /// 要素数 `n` での前処理における計算回数を返す。
57/// fn count(n: usize) -> usize {
58/// if n <= 2 {
59/// return 0;
60/// }
61/// g(n - 1)
62/// + if n.is_power_of_two() {
63/// n.trailing_zeros() as usize
64/// } else {
65/// n.next_power_of_two() / 2
66/// }
67/// - 1
68/// }
69///
70/// assert_eq!(count(3), 1);
71/// assert_eq!(count(10), 14);
72/// assert_eq!(count(1000), 7008);
73/// assert_eq!(count(1_000_000), 16_980_635);
74///
75/// /// 各段における寄与分の和を返す。
76/// fn g(n: usize) -> usize {
77/// (0..)
78/// .take_while(|&k| n >= 2_usize.pow(k + 1))
79/// .map(|k| f(k, n - 2_usize.pow(k + 1)))
80/// .sum()
81/// }
82///
83/// /// k 段目における寄与分を返す。
84/// fn f(k: u32, n: usize) -> usize {
85/// let p = 2_usize.pow(k);
86/// n / (2 * p) * p
87/// + if n / p % 2 == 1 { n % p + 1 } else { 0 }
88/// + (n + 1) / (2 * p) * (p - 1)
89/// }
90/// ```
91///
92/// # Examples
93/// ```
94/// use nekolib::ds::DisjointSparseTable;
95/// use nekolib::traits::Fold;
96/// use nekolib::utils::OpRollHash;
97///
98/// let op_rh = OpRollHash::<998244353>::default();
99/// let value_of = |s| op_rh.value_of(s);
100///
101/// let base: Vec<_> = ["abra", "cad", "abra"].iter().map(|s| value_of(s)).collect();
102/// let dst: DisjointSparseTable<_> = (base, op_rh).into();
103/// assert_eq!(dst.fold(1..=2), value_of("cadabra"));
104/// assert_eq!(dst.fold(..), value_of("abracadabra"));
105/// ```
106pub struct DisjointSparseTable<M: Monoid> {
107 buf: Vec<Vec<M::Set>>,
108 monoid: M,
109}
110
111impl<M, B> Fold<B> for DisjointSparseTable<M>
112where
113 M: Monoid,
114 M::Set: Clone,
115 B: RangeBounds<usize>,
116{
117 type Output = M;
118 fn fold(&self, b: B) -> M::Set {
119 let Range { start, end } = bounds_within(b, self.buf[0].len());
120 if start >= end {
121 return self.monoid.id();
122 }
123 let len = end - start;
124 let end = end - 1;
125 if start == end {
126 return self.buf[0][start].clone();
127 }
128 let row = ((start ^ end) + 1).next_power_of_two().trailing_zeros() - 1;
129 let row_len = 1_usize << row;
130 let row = row as usize;
131
132 if len <= 2 * row_len && row + 1 < self.buf.len() {
133 if start.is_power_of_two() && end >> (row + 1) == 1 {
134 return self.buf[row + 1][end].clone();
135 }
136 if (end + 1).is_power_of_two() && start >> (row + 1) == 0 {
137 return self.buf[row + 1][start].clone();
138 }
139 }
140
141 self.monoid.op(self.buf[row][start].clone(), self.buf[row][end].clone())
142 }
143}
144
145impl<M> From<Vec<M::Set>> for DisjointSparseTable<M>
146where
147 M: Monoid + Default,
148 M::Set: Clone,
149{
150 fn from(base: Vec<M::Set>) -> Self { Self::from((base, M::default())) }
151}
152
153impl<M> From<(Vec<M::Set>, M)> for DisjointSparseTable<M>
154where
155 M: Monoid,
156 M::Set: Clone,
157{
158 fn from((base, monoid): (Vec<M::Set>, M)) -> Self {
159 let len = base.len();
160
161 let height = len.next_power_of_two().trailing_zeros().max(1) as usize;
162 let mut buf = vec![base; height];
163
164 for i in 1..height {
165 let w = 1 << i;
166 for j in (1..).step_by(2).take_while(|&j| j * w <= len) {
167 let mid = j * w;
168 for r in (1..w).take_while(|r| mid + r < len) {
169 buf[i][mid + r] = monoid.op(
170 buf[i][mid + r - 1].clone(),
171 buf[0][mid + r].clone(),
172 );
173 }
174 }
175 }
176
177 for i in 1..height {
178 let w = 1 << i;
179 for j in (1..).step_by(2).take_while(|&j| j * w <= len) {
180 let mid = j * w - 1;
181 for l in 1..w {
182 buf[i][mid - l] = if mid > l && (l + 1).is_power_of_two() {
183 let ei = (mid - l).trailing_zeros() as usize;
184 let ej = mid;
185 buf[ei][ej].clone()
186 } else {
187 monoid.op(
188 buf[0][mid - l].clone(),
189 buf[i][mid - l + 1].clone(),
190 )
191 };
192 }
193 }
194 }
195 Self { buf, monoid }
196 }
197}
198
199impl<M> Index<usize> for DisjointSparseTable<M>
200where
201 M: Monoid,
202 M::Set: Clone,
203{
204 type Output = M::Set;
205 fn index(&self, i: usize) -> &Self::Output { &self.buf[0][i] }
206}