Skip to content

Commit

Permalink
Changed # levels.mdx
Browse files Browse the repository at this point in the history
  • Loading branch information
crafticat authored Dec 16, 2024
1 parent 07c3afc commit c2e6296
Showing 1 changed file with 94 additions and 88 deletions.
182 changes: 94 additions & 88 deletions content/6_Advanced/Wavelet.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Wavelet trees are data structures that support efficient queries for the k-th mi
</Resource>
</Resources>

### Wavelet Tree Structure
## Wavelet Tree Structure

To answer value-based queries efficiently, we'll create a segment tree where each node represents a range of values, instead of indices. Just like a normal segment tree, each subsequent level splits the range into two halves. Note that an index can appear in at most $\log(M)$ nodes.

Expand Down Expand Up @@ -254,99 +254,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 c2e6296

Please sign in to comment.