Skip to content

Commit 4f3455f

Browse files
author
Takanori MAEHARA
authored
Disjoint Sparse Table
1 parent 02236d7 commit 4f3455f

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//
2+
// Disjoint Sparse Table
3+
//
4+
// Description:
5+
//
6+
// Let `otimes` be a binary associative operator.
7+
// The disjoint sparse table is a data structure for a
8+
// sequence xs that admits a query
9+
// prod(i,j) = xs[i] `otimes` ... `otimes` xs[j-1]
10+
// in time O(1).
11+
//
12+
// The structure is a segment tree whose node maintains
13+
// prod(i,m) and prod(m,j) for all i, j in the segment.
14+
// Then prod(i,j) is evaluated by finding the node that
15+
// splits [i,j) and returning prod(i,m)*prod(m,j).
16+
//
17+
// Complexity:
18+
//
19+
// preprocessing O(n log n)
20+
// query O(1)
21+
//
22+
#include <bits/stdc++.h>
23+
24+
using namespace std;
25+
26+
#define fst first
27+
#define snd second
28+
#define all(c) ((c).begin()), ((c).end())
29+
#define TEST(s) if (!(s)) { cout << __LINE__ << " " << #s << endl; exit(-1); }
30+
31+
template <class T, class Op>
32+
struct DisjointSparseTable {
33+
vector<vector<T>> ys;
34+
Op otimes;
35+
DisjointSparseTable(vector<T> xs, Op otimes_) : otimes(otimes_) {
36+
int n = 1;
37+
while (n <= xs.size()) n *= 2;
38+
xs.resize(n);
39+
ys.push_back(xs);
40+
for (int h = 1; ; ++h) {
41+
int range = (2 << h), half = (range /= 2);
42+
if (range > n) break;
43+
ys.push_back(xs);
44+
for (int i = half; i < n; i += range) {
45+
for (int j = i-2; j >= i-half; --j)
46+
ys[h][j] = otimes(ys[h][j], ys[h][j+1]);
47+
for (int j = i+1; j < min(n, i+half); ++j)
48+
ys[h][j] = otimes(ys[h][j-1], ys[h][j]);
49+
}
50+
}
51+
}
52+
T prod(int i, int j) { // [i, j) query
53+
--j;
54+
int h = sizeof(int)*__CHAR_BIT__-1-__builtin_clz(i ^ j);
55+
return otimes(ys[h][i], ys[h][j]);
56+
}
57+
};
58+
template <class T, class Op>
59+
auto makeDisjointSparseTable(vector<T> xs, Op op) {
60+
return DisjointSparseTable<T, Op>(xs, op);
61+
}
62+
63+
int main() {
64+
vector<int> xs = {3,1,4,1,5,1};
65+
int n = xs.size();
66+
auto otimes = [](int a, int b) { return max(a, b); };
67+
auto dst = makeDisjointSparseTable(xs, otimes);
68+
69+
for (int i = 0; i < n; ++i) {
70+
for (int j = i+1; j <= n; ++j) {
71+
cout << i << " " << j << " " << dst.prod(i, j) << " ";
72+
int a = xs[i];
73+
for (int k = i+1; k < j; ++k)
74+
a = otimes(a, xs[k]);
75+
cout << a << endl;
76+
}
77+
}
78+
}

0 commit comments

Comments
 (0)