-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathprev.cpp
131 lines (104 loc) · 3.44 KB
/
prev.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include "prev.h"
#include <algorithm>
#include <climits>
#include <memory>
#define DEPTH 32
class Interval {
public:
int low;
int high;
Interval(int l, int h) : low(l), high(h) {}
};
class Node {
public:
int index;
Interval interval;
std::shared_ptr<Node> left;
std::shared_ptr<Node> right;
Node(int ind, Interval i) : index(ind), interval(i), left(nullptr), right(nullptr) {}
};
std::vector<std::shared_ptr<Node>> IntervalTree;
void pushBackRoot() {
IntervalTree.push_back(std::make_shared<Node>(IntervalTree.size(), Interval(INT_MIN, INT_MAX)));
}
// val \in Interval
bool directionLeft(Interval inter, int val) {
return val <= inter.low / 2 + inter.high / 2;
}
std::shared_ptr<Node> getChild(std::shared_ptr<Node> node, bool left) {
if (node == nullptr)
return nullptr;
return left ? node->left : node->right;
}
void link(std::shared_ptr<Node> currNode, std::shared_ptr<Node> prevNode, bool left) {
if (left)
currNode->left = getChild(prevNode, true);
else
currNode->right = getChild(prevNode, false);
}
void createChild(std::shared_ptr<Node> currNode, bool left) {
int mid = currNode->interval.low / 2 + currNode->interval.high / 2;
if (left)
currNode->left = std::make_shared<Node>(IntervalTree.size() - 1, Interval(currNode->interval.low, mid));
else
currNode->right = std::make_shared<Node>(IntervalTree.size() - 1, Interval(mid + 1, currNode->interval.high));
}
int getIndexOfChild(std::shared_ptr<Node> node, bool left) {
if ((left && node->left == nullptr) || (!left && node->right == nullptr))
return 0;
return left ? node->left->index : node->right->index;
}
void init(const std::vector<int> &seq) {
pushBackRoot();
for (int el : seq)
pushBack(el);
}
int prevInRange(int i, int lo, int hi) {
std::shared_ptr<Node> node = IntervalTree[i + 1];
bool left;
int maxIndex = 0;
for (int depth = 0; depth < DEPTH; depth++) {
if (node == nullptr)
break;
if (lo == node->interval.low) {
maxIndex = std::max(maxIndex, node->index);
break;
}
left = directionLeft(node->interval, lo);
if (left && hi > node->interval.high)
maxIndex = std::max(maxIndex, getIndexOfChild(node, false));
node = getChild(node, left);
}
node = IntervalTree[i + 1];
for (int depth = 0; depth < DEPTH; depth++) {
if (node == nullptr)
break;
if (hi == node->interval.high) {
maxIndex = std::max(maxIndex, node->index);
break;
}
left = directionLeft(node->interval, hi);
if (!left && lo < node->interval.low)
maxIndex = std::max(maxIndex, getIndexOfChild(node, true));
node = getChild(node, left);
}
return maxIndex - 1;
}
// current index: IntervalTree.size() - 1
// previous index: IntervalTree.size() - 2
void pushBack(int value) {
pushBackRoot();
std::shared_ptr<Node> currNode = IntervalTree[IntervalTree.size() - 1];
std::shared_ptr<Node> prevNode = IntervalTree[IntervalTree.size() - 2];
bool left;
for (int depth = 0; depth < DEPTH; depth++) {
left = directionLeft(currNode->interval, value);
link(currNode, prevNode, !left);
createChild(currNode, left);
currNode = getChild(currNode, left);
prevNode = getChild(prevNode, left);
}
}
void done() {
IntervalTree.clear();
}