ツバサの備忘録

主に備忘録代わりに精進記録を載せていくつもりです。

codeFlyer (bitFlyer Programming Contest)予選 C - 徒歩圏内

問題
提出コード
これを自力で解けなかったのは結構悔しいです…最近思い通りになかなか解けないですね

解法

X_j - X_i \leqq D,X_k - X_j \leqq D,D \lt X_k - X_i \leqq 2×Dとなるような(i,j,k)の組を探します。
要素が3つ存在するので、まずは真ん中を決め打ちしたときの(i,k)のペアの個数を求めることを考えます。
あるjについて、X_j - X_i \leqq DとなるようなiおよびX_k - X_j \leqq Dとなるようなkの個数は、それぞれ二分探索で求めることができます。

  • iの個数
    X_j - X_i \leqq Dを満たすことから、式変形をするとX_j  - D \leqq X_iを満たす必要があります。ということで、j-1までで、上の条件をみたすものの個数を調べるため、
    jから、X_i \lt X_j -Dとなるiの個数を引けばよいです。
    これは、二分探索を利用することで求められます。

  • kの個数
    X_k - X_j \leqq Dを満たすことから、X_k \leqq X_j + Dを満たす必要があります。
    ということで、j+1以降でこの条件を満たす区間の個数を求めるため、
    X_k \leqq X_j + Dとなるkの個数から、jを引けばよいです。

ということで、ikの個数を求められたので、(i,k)のペアの個数は、それぞれの個数の積になります。
ただし、このままだとD \lt X_k - X_iを満たさないものが存在しています。
ということで、最後にこうならないものを全体から引けば、答えが求まります。

  • D \geqq X_k - X_iとなる(i,j,k)の組の個数を求める
    D \geqq X_k - X_iとなる(i,k)のペアを決めたとき、ありうるji+1k-1です。
    今回は、kを決め打ったときに、上のD \geqq X_k - X_iをみたす(i,j)のペアの個数を求めていきます。
    D \geqq X_k - X_iとなるiの中で、最も遠いようなiをまず探します。
    これは、二分探索で求めることができます。これを仮にlとします。
    すると、(i,j)のペアは、今求めたl~今求めたk-1の中から2つの数字を選ぶ方法と同じになります。
    このとき、すべての(i,j,k)についてD \geqq X_k - X_iを満たしています。なぜなら、lがこの条件を満たすiの中で最も遠い場所になるので、それより後ろの場所をiとしても、X_kとの距離は小さくなるだけです。
    ということで、kから、X_i \lt X_k -Dとなるiの個数をP_kとしたときに、
    D \geqq X_k - X_iとなる(i,j,k)の組の個数は、
    \frac{(P_k)(P_k-1)}{2}
    となります。
    全てのkについてこれを求め、最初に数えたものから引いていけば、最終的な答えとなります。