B 問題「コミュニケーション能力(Communication Ability)」解説

満点解法

説明の簡単化のため,

かがみずくんが人物 $j$ と友達になることを考える.

$(かかる最小のコスト) = \min(|c_j-c_0|,|c_j-c_1|,...,|c_j-c_{j-1}|)$

なので,それを毎回計算すれば答えが求まる.

しかし,これを毎回時間計算量 $O(N)$ で計算していては時間切れになってしまう.

そこで,数直線上に $c_0,c_1,...,c_{j-1}$ をプロットしてみれば自明ではあるが,$|c_x-c_j|$ が最小となる$c_x$は,

であることを利用する(ただし条件を満たす $c_x$ が存在しない場合考慮しない).

これらの値を求めるためには,$c_0,c_1,...,c_{j-1}$を常にソートした列を保持しておき,それに対し二分探索を行えるようなデータ構造が必要となる.

そのためには,要素の追加・二分探索の両方が時間計算量 $O(\log N)$ で行える平衡二分木を用いると良い.

C++であれば,STL(スタンダード・テンプレート・ライブラリ)にsetという平衡二分木クラスが備わっており,lower_bound/upper_boundメソッドを用いて二分探索を行うことができる.

平衡二分木を用いた場合,今回の問題における時間計算量は $O(N \log N)$ となり時間制限に間に合う.