takumi152の競プロ日記

競プロとかその他諸々とかの記録

第3回PAST 参加記

無料回だったので参加してみました。

結果

リアルタイム受験をしました。

結果は94点で、エキスパートに認定されました。やったね。

各問題を解くまでの時間はこんな感じでした(開始=13:00、終了=18:00)。

以下に各問題について書いていきたいと思います。

※どう解いたかうろ覚えな状態で書いているので、説明が雑な部分があります。予めご了承ください

A - ケース・センシティブ

問題文はこちら

文字列をそのまま比較した場合と、小文字に変換してから比較した場合を見るだけです。

ちなみにですが、最初はsamedifferentを出せばよいと誤読して1WAを出しました(え?)

提出したコード(Python)はこちら

B - ダイナミック・スコアリング

問題文はこちら

序盤の重実装その1。

各参加者がどの問題を解いたかと、各問題の現在の得点を管理すればよいです。

提出したコード(Python)はこちら

C - 等比数列

問題文はこちら

 R = 1なら Aをそのまま出力するだけです。

 R \ge 2なら愚直にやって、答えが 10^9を超えたらその時点で計算を打ち切ればよいです。

ループ回数は高々 \lceil \log_{2}{10^9} \rceil = 30回程度なので、十分間に合います。

提出したコード(Python)はこちら

D - 電光掲示

問題文はこちら

序盤の重実装その2。

サンプルから各数字の見本を持ってきて、見本の状態と現在見ている数字の状態が全て一致しているかどうかを確認しました。

提出したコード(Python)はこちら

E - スプリンクラー

問題文はこちら

問題文の通りにグラフを作って解くだけです(雑)

 N, Q \le 200なので、愚直に O(NQ)で解いても十分間に合います。

提出したコード(Python)はこちら

F - 回文行列

問題文はこちら

行列の i列目と N-i列目の両方に存在する文字があるかどうかを調べればよいです。

setで出現した文字を管理すれば O(26 \cdot N^2) O(26 \cdot N^2 \log{N})程度ですが、愚直に全ての組を調べても O(N^3)なので間に合うと思います。

提出したコード(Python)はこちら

G - グリッド金移動

問題文はこちら

最初の位置からBFSをすれば解くことができます。が、負の座標が存在するので少し厄介です。

自分の場合は、全ての座標を+1000だけずらしてからやることで負の座標を気にする必要が無くなると思ったので、そうしました。

提出したコード(C++)はこちら

H - ハードル走

問題文はこちら

各行動を行った後、位置 Lまで到達するのに必要な最小時間をDPで求めればよいです。

 dp[i] := (位置iに到達するのに必要な最小時間) h[i] := (位置iにハードルが存在するかどうか)とすれば、遷移式は次のようになります。

  •  dp[i+1] = \min(dp[i+1], dp[i] + t1 + (h[i+1] ? t3 : 0)) (行動1を行った場合)

  •  dp[i+2] = \min(dp[i+2], dp[i] + t1 + t2 + (h[i+2] ? t3 : 0)) (行動2を行った場合)

  •  dp[i+4] = \min(dp[i+4], dp[i] + t1 + t2 * 3 + (h[i+4] ? t3 : 0)) (行動3を行った場合)

ただし、空中にいる状態でゴールする場合(行動2や行動3を行っている途中で位置 Lに到達する場合)があるので、そこの場合分けが必要になります。この場合の遷移式は、

  •  dp[L] = \min(dp[L], dp[i] + t1 / 2+ (t2 / 2) * ((L - i) * 2 - 1)

となります。

提出したコード(C++)はこちら

I - 行列操作

問題文はこちら

行列の現在の行と列の並び順を管理すればよいです。

また、転置の操作も存在しますが、これは行と列が入れ替わるという操作なので、

  • 転置が行われた回数が偶数の場合は行(または列)に対する操作をそのまま行って、

  • 奇数の場合は行(または列)に対する操作の行と列を入れ替えて操作を行う

とすればよいです。

提出したコード(C++)はこちら

J - 回転寿司

問題文はこちら

便宜上、まだ寿司を1つも食べていない子供が食べた寿司のおいしさの最大値を 0とすると、

  • 子供が食べた寿司のおいしさの最大値は、常に降順になっている

という性質があります。

これは、ある子供( aとする)が食べた寿司のおいしさの最大値が、その前の子供( bとする)が食べた寿司のおいしさの最大値よりも大きいと仮定すると、 aが食べた寿司の中でおいしさが最大のものは bが食べているはずなので矛盾する、という背理法的なやり方で示すことができます(本番ではもちろん無証明で、多分そうだろうなと信じてやりました)。

よって、各寿司が誰に食べられるかは二分探索を利用することで調べることができるので、この問題は O(M\log{N})で解くことができます。

提出したコード(C++)はこちら

K - コンテナの移動

問題文はこちら

各机の一番上にあるコンテナと、各コンテナのひとつ下のコンテナを管理することにすると、問題のサンプルの移動例は以下の画像のように表すことができます。

f:id:takumi152:20200608044255p:plain

つまり、このような移動を実現するには、以下の3つの操作を行えばよいです。

  • 移動対象のコンテナが元々あった机の一番上のコンテナを、移動先の机の一番上のコンテナにする。

  • 移動対象のコンテナのひとつ下にコンテナがあれば、それを移動対象が元々あった机の一番上のコンテナにする。

  • 移動対象のコンテナのひとつ下のコンテナを、移動先の机で元々一番上だったコンテナに(あれば)する。

上の図では分かりやすさのために連結リスト風の書き方をしていますが、vectorなどで一番上のコンテナとひとつ下のコンテナを管理することにより各移動操作を O(1)で行うことができます。よって、この問題は O(N + Q)で解くことができます。

提出したコード(C++)はこちら

L - スーパーマーケット

問題文はこちら

手前から1番目の商品の中で消費期限の値が最も大きいものがある列(インデックス)は、セグメント木を使うことで O(\log{N})で求めることができます。手前から2番目にある商品についても同様です。

よって、手前から1番目と2番目の商品について消費期限の値を調べて、手前から1番目と2番目のどちらから商品が取られたかによって次の商品への入れ替えの場合分けをすればよいです。

提出したコード(C++)はこちら

M - 行商計画問題

問題文はこちら

 Kの値の制約が非常に小さいことと、問題名から巡回セールスマン問題のような問題ではないかと予想ができます(本当か?)

実際、この予想は正しくて、 K個の街 t_1, t_2, ..., t_Kの間の最短距離をそれぞれ求めることで、(始点に戻らない)巡回セールスマン問題に帰着することができます。

ただし、制約的にnext_permutationを利用した O(K!)解法では間に合わないので、bitDPを利用した O(K \cdot 2^K)解法で解く必要があります。

ところで、この参加記を書いてて気が付きましたが、この問題の英語名は"Real Traveling Salesman"だそうです。やっぱり問題名が答えだった

提出したコード(C++)はこちら

N - 入れ替えと並び替え

問題文はこちら

とても難しかった問題。

どのような操作が行われるかを見ると、

  • 隣接する要素のswap

  • 指定した範囲のソート

があります。

愚直にやると任意の範囲に対して複数回ソートを要求されるので当然間に合いません。一方で、ソート以外の操作は、隣接要素のswapしかありません。

そこで、今までに行ったswapの操作に対して、うまく逆の操作を行うことで効率的にソートの操作を行うことができないか・・と、解いていた当時は考えていたと思います(超うろ覚え)

実際、swapのみを行った場合は転倒数は高々 Qにしかならないので、必要な部分だけバブルソートを行ってやれば効率よくソートを行うことができそうです。

では、ソートが必要な部分はどうやって管理するかというと、自分の場合は遅延セグメント木を利用して、「最後にswapが行われてからソートが行われたかどうか」を確認することで行っていました(本番ではこれしか思いつきませんでしたが、実際はsetとかでも十分だと思われます)。

これで十分間に合うだろうと信じて提出をすると、通りました(本番では計算量をちゃんと考えていませんでしたが、実際の計算量は O(Q\log{NQ})ぐらいになりそう?)

提出したコード(C++)はこちら

O - 輪投げ

問題文はこちら

今回のPASTで唯一解けなかった問題。WA投げ

DP、もしくは貪欲っぽいなと思ってずっと考えていましたが、想定解は最小コストフローだったそうです。

何を食べたらこの問題がフローの問題だと判別できるんだろうか・・?

最後に

暖色コーダーでも88点が続出していたようでした(当社調べ)が、そんな問題セットでエキスパートを取れたので、かなりの自信になったかなと思います。