絶記

絶起の記録です

2020/5/31バチャ反省(2)

久し振りにABCに出るのでウオーーーーーーーーーーーーーーーーーーーーーーミングアップにバチャをしました。

バチャ概要

リンクです。

難易度は

  • 0~400(灰)*10
  • 800~1200(緑)*2
  • 1200~1400(水色)*1

55分+2ペナで全完。水色の考察をするために組みましたが、グラフだったので瞬殺でした。

解説

緑以上の3問だけ解説と提出を書きます。

Transit Tree Path

考察と方針

クエリではx _ jとy _ jが与えられ、 x _ jからKを経由してy _ jまで移動する最短距離を求める必要があります。無向グラフなので、x _ jからKまでの最短経路Kからx _ jまでの最短経路は同じです。

また、木においてある二点をつなぐ経路は一つしか存在しないため、実は「x _ jからy _ jへの経路にKが含まれているか」は気にしなくてよいことが分かります。

つまり、事前にKを始点にした全点への最短経路を求めておき、各クエリにおいて

  • Kからx _ jまでの最短経路
  • Kからy _ jまでの最短経路

を足したものを出力すればよいです。

実装

解説を読むと「経路は一通りなのでKを根にしてDFSすればよいです」とあります(これはつまり、上で言っている「最短経路」が「経路」と言い換えられるということでもあります)が、それに気づかなかったのでKを始点にダイクストラをしました。あとは各クエリにおいて上で書いた値を出力するだけです。

提出

atcoder.jp

計算量

ダイクストラ部分がネックになって、O(NlogN)です。想定解ではO(N+Q)なのでかなり違いますが、通ればいいんです。


STring

考察と方針

とりあえず変化しなくなるまで

X = X.replace("ST", "")

を繰り返せばいいのはわかります。提出します。O(N ^ 2)なので当然TLEです。

制約的にO(N)が限界なので、大体一回のループで処理を完了しなければなりません。どうしよう....

問題文の通り、、STが1ペアとなって消滅します。これはスタックの説明でよく見る括弧列の対応と同じです。すなわち、要素をスタックに一つずつ追加していって、右端でSTのペアができていたら消す、できていなかったらなにもしない...という流れを繰り返すことで、問題文にあるSTのペアを消していくシミュレーションと同じ結果が得られます。

これはざっくりいうと、「スタックに変更があるたびに右端だけチェックすれば、右端以外はチェック済みなのでSTが含まれていることは無い」ということです。

実装

listの計算量に詳しくないのでdequeを使いました。

提出

(解説を書いていて色々改善できることに気づいたので改善しました) atcoder.jp

計算量

ループの中の処理はappend, pop, 比較だけなので定数時間です。全体では|X|回ループしているのでO(|X|)です。


joisino's travel

考察と方針

与えられたグラフの全点対最短経路は、繰り返しダイクストラをすることで簡単に求まります。

また、Rが小さいので、R個の街を訪れる順番をすべて列挙しても8!=40320回に収まります。

よって、あらかじめ全点対最短経路を求めて置き、考えられる経路すべてのコストを求めたうえで、最小値を求めればよいです。

実装

itertoolsの中のpermitations関数を使うことで、与えたリスト(今回の場合r)の順列を求めることができます。

提出

atcoder.jp

計算量

一回のダイクストラO(N+M)logN=O(N ^ 2)logNです(M \leqq N ^ 2のため)。[N]点に対して行うのでO(N ^ 3)logNで全点対最短経路を求めることができます。冷静に考えたらWFすればよくね?

まとめ

グラフが出ると解けて楽しいですね