ABC 370

ABC 370 に参加しました。

問題 A 問題 B 問題 C 問題 D 問題 E 問題
提出 AC AC AC AC -
Diff 予想 5 300 600 800 1,700
Diff 結果 11 84 228 1,088 1,453

A 問題

パターンマッチです。 ワンライナにする意味がありません

main=interact$(["Invalid","Yes","No"]!!).(`mod`3).sum.zipWith(*)[1,2].map read.words

B 問題

畳み込みの問題です。ゴリ押しワンライナ……

main=interact$show.f.map(map(pred.read).words).lines;f([n]:x)=foldl(\i j->x!!max i j!!min i j)(x!!0!!0)[1..n]+1

C 問題

コンパイルエラーと戦いました。エラーの原因は、 UM.MVector に対して VM.MVector の関数を使っていたことでした。 Haskell のコンパイルエラーは、 2 分探索とエスパーで戦うしかありません。。辛いです。

D 問題

行ごと、列ごとに Set で壁マスを持つとシミュレーションできます。

solve :: StateT BS.ByteString IO ()
solve = do
  (!h, !w, !q) <- ints3'
  !qs <- U.replicateM q ints11'

  rows <- VM.replicate h (IS.fromList [0 .. w - 1])
  cols <- VM.replicate w (IS.fromList [0 .. h - 1])

  U.forM_ qs $ \(!y, !x) -> do
    row <- VM.read rows y
    col <- VM.read cols x
    if IS.member x row
      then do
        -- この壁を削除
        let !row' = IS.delete x row
        let !col' = IS.delete y col
        VM.write rows y row'
        VM.write cols x col'
      else do
        -- 4 方の壁を削除
        let !x1 = fromMaybe (-1) $ IS.lookupLT x row
        let !x2 = fromMaybe (-1) $ IS.lookupGT x row
        let !y1 = fromMaybe (-1) $ IS.lookupLT y col
        let !y2 = fromMaybe (-1) $ IS.lookupGT y col

        let !row' = (IS.delete x2 . IS.delete x1) row
        let !col' = (IS.delete y2 . IS.delete y1) col
        GM.write rows y row'
        GM.write cols x col'

        unless (y1 == -1) $ GM.modify rows (IS.delete x) y1
        unless (y2 == -1) $ GM.modify rows (IS.delete x) y2
        unless (x1 == -1) $ GM.modify cols (IS.delete y) x1
        unless (x2 == -1) $ GM.modify cols (IS.delete y) x2

  res <- V.sum . V.map IS.size <$> V.unsafeFreeze rows
  printBSB res

Set に床マスを入れた場合は、より大きなグリッドの制約でも解くことができるそうです (hiro さんの解説) 。しかし 2 分探索パートが理解できません……。

E 問題

\(DP[i]\) を \(A_i\) で切ったときの、 \(A_i\) までの有効な切り分けの数とします。位置 \(x\) への流入は、全流入から位置 \(x - k\) からの流入を引いたものです。なるほど。

理解すればあっさり解けるのが〜青 diff 帯の DP ですが、やはり理解が難しい。

solve :: StateT BS.ByteString IO ()
solve = do
  (!n, !k) <- ints2'
  !xs <- intsU'

  let !positions = U.postscanl' (+) (0 :: Int) xs

  let (!res, !_, !_) = U.foldl' step s0 positions
        where
          -- nTot: the number of valid splits so far
          -- cnts: position -> count
          s0 = (modInt 0, modInt 1, IM.singleton 0 1)
          step (!_, !nTot, !cnts) !pos = (incoming, nTot', cnts')
            where
              !incoming = nTot - fromMaybe 0 (cnts IM.!? (pos - k))
              !nTot' = nTot + incoming
              !cnts' = IM.insertWith (+) pos incoming cnts

  printBSB res