AVL木を実装してみるの続きです。

平衡二分探索木であるAVL木を使えば「集合に含まれている値の最小値(最大値)」や「集合に含まれている要素のうち x 以上である最小値(x 以下である最大値)」を求める処理を高速に実行することができるようになります。

D – Cutting Woods

D – Cutting Woods

問題の趣旨は以下のとおりです。

1メートルごとに切れ目がついたLメートルの木がある。
クエリ 1 では x メートル部分で木を切断する。
クエリ 2 では x メートル部分を含む木の長さを出力せよ。

最初に木の端の座標である 0 と L をAVL木に格納しておきます。

木が切断されたらAVL木にその部分の座標を格納します。

木の長さを求めるときは、入力された値を x とすると、AVL木に格納されている値のうち x 以上である最小値から x 以下である最大値を引けばよいです。

AviTreeクラスの定義は AVL木を実装してみる を参照してください。

E – Best Performances

E – Best Performances

問題の趣旨は以下のとおりです。

すべての要素が 0 で長さが N の配列がある。
Q 回にわたって要素のひとつが更新されるので、その値が大きいもの K 個の総和を計算し、これを出力せよ。

実際に値が大きいもの K 個がどれなのかを調べて総和を計算していたのでは制限時間以内に間に合わせることはできません。

そこで配列の要素を上位 K 個とそれ以外のもの(high, low)にわけます。そして値が a から b に更新されたら

① a が high にある場合
a を high から削除
b が low_max 以上なら high に追加
そうでないなら low に追加して low_max を high に移動

② a が low にある場合
a を low から削除
b が high_min 以下なら low に追加
そうでないなら high に追加後、high_min を low に移動

③ 最初はすべての要素が 0 なので総和は 0。high に値が追加、削除されるたびに差分から総和を更新してこれを出力する。

E – Least Elements

E – Least Elements

これも前問と似たような問題です。長さ M の区間を前から後ろにずらしながら区間内の下位 K 個の総和を求めよという問題です。

最初の K 個はなにも考えずにそのまま low に入れます。

M – K 個はlow_maxよりも小さければ low に入れ、代わりに low_max を high に移動させます。そうでなければそのまま high に格納します。

最後の N – M 個は上と同じ要領で追加処理をおこなったあと、A[i – M]の削除処理をおこないます。削除対象が low と high のどちらに格納されているかを調べて削除します。もし low から削除した場合は high_min を high から low へ移動させます。