Open hockyy opened 3 years ago
Beware that my implementation actually uses O(M + N log M)
space (where M
is the difference between the smallest and largest elements), because it constructs a complete tree with M
leaves. It can be reduced to N log M
by constructing the tree lazily, but the operations will require a little more code.
Also, the quantile query is the only interesting query IMO. Rank and rectangle queries are just as easily answered by other trees such as persistent segment trees.
Quantile can also be done with persistent segment trees: recurse on the segtrees for L and R together, descend to the left if k < L->left->sum + R->left->sum
else to the right. As I see it wavelet trees and persistent segtrees are basically isomorphic, they just store pointers differently. The only reason to use wavelet trees is if you were able to combine it with another data structure (e.g. I'm not sure off hand how to solve the "toggle" queries described in https://users.dcc.uchile.cl/~jperez/papers/ioiconf16.pdf with persistent segtrees), or if you used a bit-compressed version to save a factor ~32 on memory usage.
https://codeforces.com/profile/nor helpfully links to https://judge.yosupo.jp/submission/60640 as a nice bit-compressed version. It also stores bits for each of the log M layers consecutively ("wavelet matrix"), which makes them dense even at the leaves and avoids some memory indirection. It's very long though.
https://gitlab.au.dk/BeyondBallmersPeak/kactl/-/blob/4fde3a49533621e4178d8dffa29bf0701fe8f8db/content/data-structures/WaveletTree.h
Here is a good implementation of it.
Here is another good implementation https://usaco.guide/problems/kattis-easy-query/solution