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
//! 分解可能なクエリ。
//!
//! ## Preliminaries
//!
//! 集合 $`S\subseteq U`$ と要素 $`x\in U`$ に関する問題 $`Q_S(x)`$ を考える。
//! $`S\cup T`$ に対する問題を解くにあたって、何らかの二項演算 $`\square`$ が存在して
//! ```math
//! Q_{S\cup T}(x) = Q_S(x) \mathop{\square} Q_T(x)
//! ```
//! と書けるとき、問題 $`Q`$ は *decomposable* であるという。
//!
//! ## Theorems
//!
//! 二種類のクエリを考える。
//!
//! - $`x`$ が与えられ、$`S \xgets{\cup} \{x\}`$ で更新する。
//! - $`x`$ が与えられ、$`Q_S(x)`$ を出力する。
//!
//! $`Q_S(x)`$ が $`\angled{f(|S|), g(|S|)}`$ 時間で解けるとき、$`n`$ 個のクエリを $`O((f(n) + n\cdot g(n))\log(n))`$
//! 時間でオンライン処理できる。
//! ただし、$`f(n)\in n^{\Omega(1)}`$, $`g(n)\in n^{o(1)}`$ とし、$`\square`$ の計算も $`O(g(n))`$ 時間でできるとする。
//!
//! たとえば、$`Q_S(x)`$ が $`\angled{O(|S|\log(|S|)), O(\log(|S|))}`$ 時間で解けるなら、$`n`$ 個のクエリを $`O(n\log(n)^2)`$ 時間で処理できる。
//!
//! ## Ideas
//!
//! $`i`$ 番目の更新クエリの値を $`x_i`$ として、次のようなセグ木をイメージする。
//!
//! - $`i`$ 番目の葉に $`\{x_i\}`$ を持つ。
//! - 子が $`S_L`$, $`S_R`$ を持っている頂点は $`S_L\cup S_R`$ を持つ。
//! - $`S`$ を持つ頂点では $`Q_S`$ のためのデータ構造を保持する。
//!
//! 更新クエリを $`k`$ 個処理している状態では、$`[0\lldot k)`$ をカバーする区間にあるデータ構造を用いて各々を処理し、$`\square`$ で合成する。
//!
//! 実際にはこのセグ木の各ノードは更新せず、また各ノードを陽に持っておく必要もない。
//! 次の擬似コードに示すようにして、高々 $`\log_2(n)`$ 個のデータ構造を保持しておけばよい。
//!
//! `meld` の際には、`other` の各要素を直接 `self` に追加してもよいし、一旦 `.into_iter()`
//! のようなことをしてから再構築してもよい。
//!
//! ```
//! enum Query<T> {
//! Union(T),
//! Search(T),
//! }
//! use Query::*;
//! let qs = Vec::<Query<()>>::new();
//!
//! struct Ds<T> {
//! // ...
//! # _phd: std::marker::PhantomData<T>,
//! }
//! impl<T> Ds<T> {
//! pub fn singleton(elt: T) -> Self {
//! // ...
//! # Self { _phd: std::marker::PhantomData }
//! }
//! pub fn search<U>(&self, elt: &T) -> U {
//! // ...
//! # unimplemented!()
//! }
//! pub fn meld(&mut self, other: Self) {
//! // ...
//! }
//! }
//! # let id = ();
//! # fn compose(_: (), _: ()) {}
//!
//! let mut clx = vec![];
//! let mut count = 0_usize;
//! for q in qs {
//! match q {
//! Union(x) => {
//! count += 1;
//! clx.push(Ds::singleton(x));
//! for _ in 0..count.trailing_zeros() {
//! let tmp = clx.pop().unwrap();
//! clx.last_mut().unwrap().meld(tmp);
//! }
//! }
//! Search(x) => {
//! let _ = clx.iter().map(|si| si.search(&x)).fold(id, compose);
//! }
//! }
//! }
//! ```
//!
//! ## References
//!
//! - <https://erikdemaine.org/papers/Retroactive_TALG/paper.pdf>
//! - 命名を参考にした。
//! - <https://atcoder.jp/contests/abc244/submissions/30254752>
//! - 実装を参考にした。