同じアレイに対して複数のクエリを実行している場合は、セグメント ツリーを使用できます。これらは通常、範囲の最小/最大および範囲の合計クエリを実行するために使用されますが、範囲の中央値を実行するように変更できます。
n 間隔のセットのセグメント ツリーは、O(n log n) ストレージを使用し、O(n log n) 時間で構築できます。範囲クエリは O(log n) で実行できます。
範囲セグメント ツリーの中央値の例:
セグメント ツリーを下から上に構築します (上から下に更新します)。
[5]
[3] [7]
[1,2] [4] [6] [8]
1 2 3 4 5 6 7 8
ノードがカバーするインデックス:
[4]
[2] [6]
[0,1] [3] [5] [7]
0 1 2 3 4 5 6 7
4 ~ 6 の範囲インデックスの中央値のクエリは、次の値のパスをたどります。
[4]
[5]
0 1 2 3 4 5 6 7
中央値を検索すると、クエリの合計要素数 (3) がわかり、その範囲の中央値は 2 番目の要素 (インデックス 5) になります。したがって、基本的には、値 [1,2] (インデックス 0,1) を持つノードであるインデックスを含む最初のノードを検索しています。
範囲 3 ~ 6 の中央値の検索は、同じノードにある 2 つのインデックス (4,5) を検索する必要があるため、もう少し複雑です。
[4]
[6]
[5]
0 1 2 3 4 5 6 7
セグメントツリー
セグメント ツリーの範囲最小クエリ