-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsqrt_tree.cpp
102 lines (99 loc) · 4.82 KB
/
sqrt_tree.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int get(int layer, vector <int> &nums, vector <vector <int> > &precompute, vector <vector <int> > &suff, vector <vector <int> > &pref, vector <vector <int> > &startIdx, vector <int> &lg, int l, int r, int ll, int rr, int init = 0) {
if (ll >= rr) return nums[ll];
if (ll + 1 >= rr) return nums[ll] | nums[rr];
int b = lg[r - l];
while ((ll - l) / b == (rr - l) / b) { //add binary search or use better indexation
l += (ll - l) / b * b;
if (r > l + b) r = l + b;
b = lg[r - l];
layer++;
}
int ans = init; //block[layer]
ans |= pref[layer][ll];
ans |= suff[layer][rr];
int wl = (ll - l) / b + 1, wr = (rr - l) / b - 1;
if (wl <= wr) {
int where = startIdx[layer][l], m = (r - l) / b;
int w = lg[wr - wl + 1];
//accurately
int idx = m * w - (w >= 2 ? ((1 << (w - 1)) - 1) : 0);
//ans |= precompute[layer][where + idx + (rr / b - 1) - (ll / b + 1)];
//ans |= precompute[layer][where + ll / b + 1]
ans |= precompute[layer][where + idx + wl];
//ans |= precompute[layer][where + rr / b - 1 - t]
ans |= precompute[layer][where + idx + wr - (1 << w) + 1];
//cout << ' ' << ans << '\n';
//if ((rr - l) / b - 1 - (1 << w) + 1 < (ll - l) / b + 1) while (true);
}
return ans;
}
void build(vector <int> &nums, vector <vector <int> > &precompute, vector <vector <int> > &suff, vector <vector <int> > &pref, vector <vector <int> > &startIdx, vector <int> &lg, vector <int> &ptr, int layer, int l, int r, int init = 0) {
if (l + 1 >= r) return;
int b = lg[r - l];
int m = (r - l) / b;
startIdx[layer][l] = ptr[layer];
ptr[layer] += m * b + 2;//
//if (ptr[layer] >= precompute[layer].size()) cout << "FUCK\n";
for (int it = l; it < r; it += b) {
int ll = it, rr = min(r, it + b);
//startIdx[layer][ll] = ptr[layer]++;
for (int i = ll; i < rr; ++i) {
suff[layer][i] = nums[i];
if (i > ll) suff[layer][i] |= suff[layer][i - 1];
//precompute[[(it - l) / b * (n / b)] |= nums[i];
}
for (int i = rr - 1; i >= ll; --i) {
pref[layer][i] = nums[i];
if (i + 1 < rr) pref[layer][i] |= pref[layer][i + 1];
}
}
int where = startIdx[layer][l];
//(n/b)*(n/b+1)/2 [x; y] -> x*(n/b)+y-x
//[m] [m-1] [m-2] .. [m-2^x] [m-x] ..
for (int w = 0; (1 << w) <= m; ++w) {
for (int i = 0; i + (1 << w) - 1 < m; ++i) {
int idx = m * w + i - (w >= 2 ? ((1 << (w - 1)) - 1) : 0);
//if (idx > m * b + 1) while(true);
precompute[layer][where + idx] = (w == 0 ? pref[layer][l + i * b] :
precompute[layer][where + m * (w - 1) - (w >= 2 ? ((1 << (w - 2)) - 1) : 0) + i] |
precompute[layer][where + m * (w - 1) - (w >= 2 ? ((1 << (w - 2)) - 1) : 0) + i + (1 << (w - 1))]);
//for (int j = i + 1; j < m; ++j) { //geniucos's suggested using sparse-table here but finding indices are tough
// precompute[layer][where + idx + j - i] = precompute[layer][where + idx + (j - i - 1)] | pref[layer][l + j * b];
//}
}
}
for (int i = 0; i < m; ++i) {
if (min(r, l + (i + 1) * b) - (l + i * b) > 1) {
build(nums, precompute, suff, pref, startIdx, lg, ptr, layer + 1, l + i * b, min(r, l + (i + 1) * b), init);
}
}
}
int minimumSubarrayLength(vector<int>& nums, int k) {
const int D = 5, overhead = 3; //2^(2^D)
int N = (int)nums.size();
vector <vector <int> > precompute(D + 1, vector <int>(N *2 + overhead));
vector <vector <int> > suff(D + 1, vector <int>(N + 1)), pref(D + 1, vector <int>(N + 1));
vector <vector <int> > startIdx(D + 1, vector <int> (N));
vector <int> lg(N + 1), ptr(D + 1, 0);
for (int i = 1; i <= N; ++i) {
lg[i] = lg[i - 1] + ((1 << (lg[i - 1] + 1)) <= i);
}
build(nums, precompute, suff, pref, startIdx, lg, ptr, 0, 0, N, 0);
int ans = N + 1;
for (int i = 0, j = -1; i < N; ++i) {
if (j < i - 1) j = i - 1;
for (; j + 1 < N && get(0, nums, precompute, suff, pref, startIdx, lg, 0, N, i, j + 1) < k; ++j);
if (j + 1 < N && get(0, nums, precompute, suff, pref, startIdx, lg, 0, N, i, j + 1) >= k) ans = min(ans, j + 1 - i + 1);
}
return ans > N ? -1 : ans;
}
} sol;
int main() {
vector <int> tmp = {2, 1, 8};
cout << sol.minimumSubarrayLength(tmp, 10) << '\n';
return 0;
}