📚

AtCoder Beginner Contest ABC408 解法メモ

に公開

文中で使用しているのは、PythonライクでAtCoderに最適な言語の1つNimです

ABC408

ABC408A - Timeout

解法

Tの初項に0を加え、iが1..Nのすべての項で
T[it]<=T[it-1]+SだったらYes、
そうでなけれはNoと出力すればよい
ACコード

メモ

Tiが次の肩叩きまでの「間の時間」と誤読した

ABC408B - Compression

解法

AをHashSetにしてからSeqに戻して、Sortすればよい
ACコード

メモ

A.sorted.deduplicateでもよい
ACコード

ABC408C - Not All Covered

解法

各城壁を守っている砲台の数を表す配列cを作れば、答えは、その配列の最小値となる
それには、逆に、各砲台の守る城壁の範囲にある各ciをカウントアップしていけばよく、
計算量を勘案すれば、
c[L]+=1; c[R+1]-=1
としてから、累積和をとるimos法を用いるとよい
ACコード

ABC408D - Flip to Gather

解法

目標となる状態は、「0のかたまり」+「1のかたまり」+「0のかたまり」である
dp[先頭からi番目まで][どのかたまりにいるか]=変更しなければならない文字の数
とするDPを考えれば、
dp[0][0]=S[0]; dp[0][1]=1-S[0]を初期値に、
dp[i][0]=dp[i-1][0]+S[i]
dp[i][1]=min(dp[i-1][0]+1-S[i],dp[i-1][1]+1-S[i])
dp[i][2]=min(dp[i-1][1]+S[i],dp[i-1][2]+S[i])
と遷移させればよい
dp[^1].minが答え
ACコード

メモ

しばらく問題意図が全くわからなかった
題意からランレングス圧縮、制約から尺取り法を疑うも不能だった

ABC408E - Minimum OR Path

解法

すべてのwiのorを最小にするための経路とは、2進数にして考えれば、
(左のビットがそれより右のビットに関係なく大小関係を左右するので)全wi30桁目のorを可能なら0にする(避けられなければ1とする)経路のうち、29桁目のorを可能なら0にする経路のうち、と順番に1桁目まで狭めていった経路であるはずで、
そのときの各桁の結論(0にできれば0、そうでなければ1)を合わせたものが求める答えである
辺の採否を記録する配列を用意し、
iを29..0としながら、
いちいちwi shr i and 1を重みとしたダイクストラをして各桁を決めていく
0だった場合、wiの当該ビットが1の辺は以降使わないため、不使用のフラグを立てていけばよい
ACコード

メモ

wi2進数での各桁は当然bitであるから、ダイクストラでなく、0のまま0からN-1まで行けるか否かのUnion-Findでもよい
具体的には、(未確定の桁は判断に入れないためにすべて1にすべく)a=2^30-1を初期値に、
iを29..0としながら、いちいち
一旦、a-=1 shl iにした(注目桁を一旦0にした)後に、
a or wi==aになれば(これまでの左桁もふまえつつ、注目桁もorをしても0のままであれば)uvをmergeする処理を全辺に対して行い、
結果、0N-1がsameでなければ(0のまま0からN-1まで行けないのであれば)、改めてa+=1 shl iとしていけばよい
最後のaが答えとなる
ACコード


反復学習にはmochiがおすすめ
全問入ったdeckはこちら

Discussion