0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

List<T>.BinarySearch(二分探索)を活用しようとして適用範囲間違えた話

Posted at

ABC370 D Cross Explosion の 解法と自作回答

ABC370 D の復習をしていたのだけど、解説では二分探索を使って破壊した壁の管理を行えばよいとなっていた。
二分探索なら前回の記事(C# で lower_boundをListの拡張関数として実現する)で書いた、Listを拡張したLowerBoundですぐ見つかる!と意気込んで回答した。
結果はTLEがぼこぼこ出る。再帰で書いた初回の回答と変わらん処理速度。

なんでなんだ。。。

原因の発見

これ、落ち着いてみたらわかるんだけど、探索した後に削除するんだよね。
LowerBoundでindexはわかっているから、List.RemoveAtすればO(1)だろ!と思ってたら、List.RemoveAtは、計算量O(N)。
内部的には該当要素を削除した後、後続の値を詰める処理が発生するとのこと。
先頭に近ければ近いほど前に詰める処理が発生するそうでした。

そりゃ再帰で消す場所探すのと変わんないのよ。

List.BinarySearchの適用できる場所

挿入も削除と同じでList.InsertはO(N)になるので、削除と同じ。
つまり、BinarySearchは検索だけで挿入や削除を伴う場合はListを使い続ける限り改善しない。
前回のABC371 Dは検索だけでよかったからAC出せたということでした。

結論

標準コレクションや関数は中身ちゃんと把握してから使おうね。
(それはそう。)

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?