Skip to content

Commit

Permalink
fixed latex.mdx
Browse files Browse the repository at this point in the history
  • Loading branch information
crafticat authored Jan 7, 2025
1 parent eae9a5c commit d640ae1
Showing 1 changed file with 96 additions and 90 deletions.
186 changes: 96 additions & 90 deletions content/6_Advanced/Wavelet.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ To answer value-based queries efficiently, we'll create a segment tree where eac
Let's say our array is: $[3,5,3,1,2,2,3,4,5,5]$
Each node has an array representing the indices of every number between $l$ and $r$

![Wavelet Tree Visualization](./assets/diagram.png)
![Wavelet Tree Visualization](./assets/wavelet_tree_diagram.png)

### Solution - Range K-th Smallest
Before we solve this problem, let's consider a simpler version where we are asked, given a range, to count the number of occurrences of value $x$.
Expand All @@ -54,10 +54,10 @@ $$
\texttt{occurrences}(l, r) = \texttt{occurrences}(r) - \texttt{occurrences}(l)
\end{aligned}
$$
When occurrences(y) is the number of occurrences of x till y
When $\texttt{occurrences}(y)$ is the number of occurences of x in the first y elements.
aka
$$
\text{occurrences}(y) = \sum_{i=1}^{y} \mathbb{1}(x_i = x)
\text{occurrences} = \sum_{i=1}^{y} \mathbb{1}(x_i = x)
$$

This reduces the problem to counting the number of occurrences in a prefix.
Expand Down Expand Up @@ -259,99 +259,105 @@ using namespace std;
using namespace __gnu_pbds;
template <class T>
using Tree =
tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

struct Segment {
Segment *left = nullptr, *right = nullptr;
int l, r, mid;
bool children = false;
Tree<pair<int, int>> indices; // index, value

Segment(int l, int r, const Tree<pair<int, int>> &indices)
: l(l), r(r), mid((r + l) / 2), indices(indices) {}

// Sparse since values can go up to 1e9
void update() {
if (children) { return; }
children = true;

if (r - l > 1) {
// Split the indices for left and right child
Tree<pair<int, int>> leftIndices, rightIndices;
for (auto [index, value] : indices) {
if (value < mid) leftIndices.insert({index, value});
else rightIndices.insert({index, value});
}

left = new Segment(l, mid, leftIndices);
right = new Segment(mid, r, rightIndices);
}
}

int find_k_smallest(int a, int b, int k) {
update();
if (r - l <= 1) return l;

int lb = left->indices.order_of_key({a, -1});
int lr = left->indices.order_of_key({b, -1});
int inLeft = lr - lb;

if (k <= inLeft) return left->find_k_smallest(a, b, k); // Appears in left
else return right->find_k_smallest(a, b, k - inLeft); // Appears in right
}

void update(int index, int v, int old_v) {
update(old_v, index, false);
update(v, index, true);
}

void update(int v, int index, bool insert_operation) {
if (insert_operation) indices.insert({index, v});
else indices.erase({index, v});

update();
if (r - l <= 1) return;

if (v < mid) left->update(v, index, insert_operation);
else right->update(v, index, insert_operation);
}
Segment *left = nullptr, *right = nullptr;
int l, r, mid;
bool children = false;
Tree<pair<int,int>> indices; // index, value

Segment(int l, int r,const Tree<pair<int,int>> &indices) :l(l), r(r), mid((r + l) / 2), indices(indices) {

}

// Sparse since values can go up to 1e9
void update() {
if (children) {return;}
children = true;

if (r - l > 1) {
// Split the indices for left and right child
Tree<pair<int, int>> leftIndices, rightIndices;
for (auto [index, value] : indices) {
if (value < mid)
leftIndices.insert({index, value});
else
rightIndices.insert({index, value});
}

left = new Segment(l,mid, leftIndices);
right = new Segment(mid,r, rightIndices);
}
}

int find_k_smallest(int a, int b, int k) {
update();
if (r - l <= 1) return l;

int lb = left->indices.order_of_key({a, -1});
int lr = left->indices.order_of_key({b, -1});
int inLeft = lr - lb;

if (k <= inLeft)
return left->find_k_smallest(a,b,k); // Appears in left
else
return right->find_k_smallest(a,b, k - inLeft); // Appears in right
}

void update(int index, int v, int old_v) {
update(old_v, index, false);
update(v, index, true);
}

void update(int v, int index, bool insert_operation) {
if (insert_operation) indices.insert({index, v});
else indices.erase({index, v});

update();
if (r - l <= 1) return;

if (v < mid)
left->update(v, index, insert_operation);
else
right->update(v, index, insert_operation);
}
};

int main() {
int n, q;
cin >> n >> q;

Tree<pair<int, int>> indices;
for (int i = 0; i < n; ++i) { indices.insert({i, 0}); }

Segment seg(0, 1e9 + 2, indices);
vector<int> arr(n);

for (int i = 0; i < n; ++i) {
int v;
cin >> v;
seg.update(i, v, arr[i]);
arr[i] = v;
}

for (int i = 0; i < q; ++i) {
int t;
cin >> t;
if (t == 1) {
int a, b, k;
cin >> a >> b >> k;
k++;
cout << seg.find_k_smallest(a, b, k) << " ";
} else {
int a, b;
cin >> a >> b;
seg.update(a, b, arr[i]);
arr[i] = b;
}
}

return 0;
int main() {
int n, q; cin >> n >> q;

Tree<pair<int,int>> indices;
for (int i = 0; i < n; ++i) {
indices.insert({i,0});
}

Segment seg(0,1e9 + 2,indices);
vector<int> arr(n);

for (int i = 0; i < n; ++i) {
int v; cin >> v;
seg.update(i, v, arr[i]);
arr[i] =v;
}

for (int i = 0; i < q; ++i) {
int t; cin >> t;
if (t == 1) {
int a, b, k; cin >> a >> b >> k;
k++;
cout << seg.find_k_smallest(a,b,k) << " ";
} else {
int a, b; cin >> a >> b;
seg.update(a, b, arr[i]);
arr[i] = b;
}
}

return 0;
}

```
</CPPSection>
Expand Down

0 comments on commit d640ae1

Please sign in to comment.