Loading [MathJax]/jax/output/CommonHTML/jax.js

目次

Sky株式会社プログラミングコンテスト2023(AtCoder Beginner Contest 329)E,G 問題メモ

Sky株式会社プログラミングコンテスト2023(AtCoder Beginner Contest 329)

E - Stamp

E - Stamp

問題

解法

M が小さいので、「Si 文字目と合わせることが可能な T のindexの集合」を持って、S の左から状態を管理する。

   12345
T: ABABC

S: A B A B A B C C A B C
   1 2 3 4
       1 2 3 4 5
           1 2
                 5
                   1 2
                   3 4 5

Si 文字目と合わせられる T のindexの集合を Di とする。(たとえば D3={1,3},D4={2,4} など)

Di1 がわかっているとき、Di は、以下を合わせたものとなる。

で、途中で Di がなくなったらアウト。

なくならずに最後までいって、MDN に含まれていれば成功となる。

Python3

G - Delivery on Tree

G - Delivery on Tree

問題

解法

比較的素直な解法だが、素直にやれば解けるという確信に至るまでの丁寧な考察と、実装力が問われる。

可能不可能の判定

まず、可能不可能を判定する。

  C     こんな(S,T)があったら、Cからは左を先に訪れる必要がある
  /\
 S○
   |
   T

これがボール間で矛盾すると答えは“0”。

矛盾せず、子が2個ある各頂点につき「左/右を先に訪れなければならない」「どちらでもよい」が決まったとする。

この「どちらでもよい」でどうするかが唯一の自由度となるが、 その頂点を訪れたときに既にカゴに積まれていたボールの個数によっては、どちらか/両方が不可能な場合もある。

個数ごとに場合分けが必要そう。(制約も NK=107 といい感じだし)

各頂点ですべき操作は決まる

ある頂点でカゴにボールを積み下ろしする最適な順番は、無駄なボールを積まないことを意識するとある程度決まる。
仮に、先に訪れる子を左の子とする。

この操作と異なる手順でボールを積み下ろししても、悪くなることはあってもよくなることはない。
(※悪くなる=v に来た時点でのカゴのボールの個数が同じ状況で、上記の操作では K 個を超えないが、異なる操作では超えてしまう)
(※よくなる=v に来た時点でのカゴのボールの個数が同じ状況で、上記の操作では K 個を超えてしまうが、異なる操作では超えない)

なので、親・左・右別に、Si=v,Ti=v となる個数、計6通りを数えておくと、操作を追えそう。

子が1個なら①~⑦⑬⑭、子がない葉頂点なら①②⑬⑭だけでよいが、いずれにしろ最適な操作は決まる。

木DP

i,j に対し、①~⑭の操作をたどることで遷移を考える。
先ほどの操作の番号を、そのまま積み下ろしするボールの個数として扱うと、

となる。ただし、l,rv の左右の子、⑤は「左に行って帰ってきた際に変動するボールの個数(左の部分木内で積まれた数-下ろされた数)」とする。
⑤や⑩は、Si に+1、Ti に-1をして、葉から根に向かって累積和を取っていくことで各頂点計算できる。

各操作の途中で 0 個を下回ったり、K 個を超えるような k は無効なので、その場合は DP[v,k]=0 となる。
②,③,⑤,⑦,⑧,…,⑬ でカゴのボールの個数が変化するごとに逐一個数チェックし、途中一度でも超えるとアウト。

上記の遷移(A)は、子が1個の場合は DP[l,k+] のみとなる。
また、どちらを先に訪れても良い頂点なら、右頂点を先に訪れた場合も同様に計算して足し合わせる。

このように木DPをおこない、最終的に DP[1,0] が答えとなる。O(NK)

Python3