計算量を落とそうとしたらTLEした話

ABC265-Eにて、無理やり計算量を落とそうとしたら、TLEしたので、注意喚起も含め、記事にします。
↓問題

やろうとしたこと

まずはコードをご覧ください。(75行目からmain関数)

だめだったコード(TLE)

うまくいったコード(AC)

はい。やりたかったことは、障害物のある部分を$${O(1)}$$で判定することです。

具体的には、

// TLE
unordered_map<int,unordered_map<int,bool>> ng;

のようにすることで、$${ng[x][y]}$$でフラグ管理をし、存在するかを$${O(1)}$$で取得できると考えました。

実際はこんな高速化は必要なく set<pair<int,int>> で十分だったので、非常に無駄な時間を費やしたわけです。

なぜこのようにしたか

unordered_set/map はhash関数が定められている型のみをキーとして利用できます。つまり、

unordered_set<pair<int,int>> ng;// Compilation Error

はpair型のhash関数が定義されていないため、使えません。
なのでネストしちゃえ!となりました。

敗因

$${ng[x][y]}$$で取得する際に、その要素が存在しなくても生成されてしまいます。
その結果、毎回のループで$${ng[x][y]}$$が存在しない場合に要素が生成され続け、致命的に遅くなってしまったのです。

結論

unordered_mapを配列のようにフラグ管理に使うのはやめよう。
どうしても使うとするならば、.count()を使うことで要素が生成されないようにしよう。

でもそれをやるなら

unordered_map<int,unordered_set<int>> ng;

にして突っ込んでいけばcountするからよかったよね。(反省)


以上、無駄に計算量を落とそうとしてTLEした話でした。

ちなみに、無駄に落とそうとしていなければ(最初からset<pair<int,int>>でやっていれば)、初回提出時に水上位~青パフォ取れていました。
悲しいね。

この記事が気に入ったらサポートをしてみませんか?