「Cでのローリング中央値」の質問に対してこの回答をしました
順序統計量を使用したc++データ構造の最新の実装が見つからなかったため、両方のアイデアをトップコーダーリンクに実装することになりました(編集の一致:FloatingMedianまでスクロールダウン)。
2つのマルチセット
最初のアイデアは、データを2つのデータ構造(ヒープ、マルチセットなど)に分割し、挿入/削除ごとにO(ln N)を使用するため、大きなコストをかけずに分位数を動的に変更することはできません。つまり、ローリング中央値、またはローリング75%を持つことができますが、同時に両方を持つことはできません。
セグメントツリー
2番目のアイデアは、挿入/削除/クエリにO(ln N)であるが、より柔軟なセグメントツリーを使用します。すべての「N」の中で最も良いのは、データ範囲のサイズです。したがって、ローリング中央値に100万アイテムのウィンドウがあり、データが1..65536から変化する場合、100万のローリングウィンドウの移動ごとに必要な操作は16回だけです。(そして、65536 * sizeof(counting_type)バイトのみが必要です(例:65536 * 4))。
GNU注文統計ツリー
諦める直前に、stdlibc++には順序統計ツリーが含まれていることがわかりました!!!
これらには2つの重要な操作があります。
iter = tree.find_by_order(value)
order = tree.order_of_key(value)
libstdc ++の手動policy_based_data_structures_testを参照してください(「分割して結合」を検索してください)。
c ++ 0x / c++11スタイルの部分的なtypedefをサポートするコンパイラの便利なヘッダーで使用するためにツリーをラップしました。
#if !defined(GNU_ORDER_STATISTIC_SET_H)
#define GNU_ORDER_STATISTIC_SET_H
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
// A red-black tree table storing ints and their order
// statistics. Note that since the tree uses
// tree_order_statistics_node_update as its update policy, then it
// includes its methods by_order and order_of_key.
template <typename T>
using t_order_statistic_set = __gnu_pbds::tree<
T,
__gnu_pbds::null_type,
std::less<T>,
__gnu_pbds::rb_tree_tag,
// This policy updates nodes' metadata for order statistics.
__gnu_pbds::tree_order_statistics_node_update>;
#endif //GNU_ORDER_STATISTIC_SET_H