値の探索

int型の配列内に指定された整数が存在するかを調べる問題。配列はすでにソートされています。配列のサイズは最大で200,000です。

なにも考えずに以下の方法では時間がかかりすぎであり不合格。

ではこれはどうか? ソートされているのだから配列から取り出した値が探している値より大きくなった段階で「存在しない」と判断します。

しかし、たいした解決策にはなっていないらしくダメなものはダメ。

正しいやり方はこれ。対象とする探索範囲の中央の値と探索したい値を比較します。これで探索範囲を半分に減らせます。これを繰り返せば無駄な探索をする必要がなくなります。これならnとqが200000の場合でもわずか0.74 秒で完了します。なにも考えずに最初からループを回して探すのとは大きな違いです。

lower_bound

これはソートすれば解決しそう。n、qの最大値は200000なので実際に200000個の乱数を生成してソートにかかる時間を計測してみます。

結果は88ミリ秒。あとは上記と同じ方法でよいのですが、配列内にその値があるかどうかはわかりません。境界線を知る必要があります。そこで配列のなかにある値以上のものの個数を求めるGetCount1メソッドを定義します。

upper_bound

今度は与えられた数より大きい要素の数を求める問題です。「以上」ではなく「より大きい」なので同じ数だとカウントしません。

一箇所を変えるだけなのですが、解説では「3つめの引数に1大きな値を渡すことでも問題を解くことができる」とのこと。

ある範囲に含まれている整数の個数

いよいよラスボスです。配列内の整数のうち、a 以上 b 以下の個数を求めよという問題です。

これまで同様に数列をソート、a 以上の値が最初に現れる位置から b より大きい値が最初に現れる位置を引けば出力すれば、a 以上 b 以下の個数を取得できます。