AtCoder ABC322 振り返り
はじめに
遅くなりましたが、2回目のAtCoder 振り返りです!
言語はHaskellです!
結果
前回と同じく、A, B 2完でCがTLEでした。
A, Bまでスムーズに解けたのですが、Cでつまづいてしまった感じです。
レーティングは次の振り返りで投稿します。
問題の振り返り
A - First ABC 2
特に苦労はなかったです。 `isInfixOf` が便利でした。
B - Round-Robin Tournament
これも特に問題なかったです。
C - Festival
出力結果はあっていたのですが、会えなくTLEで撃沈しました。
原因はここで、ループごとにfindを実行してしまっていたので、O(N^2)になっていたのですね。そこに気づかずTLEで終わりました。
fireworkDays :: Int -> [Int] -> [Int]
fireworkDays n days = map distancesToNextFireWork [1 .. n]
where
s = S.fromList days
distances = zip (0 : days) days
distancesToNextFireWork i
| S.member i s = 0
| otherwise = snd (fromJust (find (\(start, end) -> i >= start && i <= end) distances)) - i
実際はこんな風に、差分を計算したリストを作れば、O(N)で計算できるのでACになります。(回答はhttps://atcoder.jp/contests/abc322/submissions/46149193に投稿しています。)
solve :: [Int] -> [Int]
solve as = fireworkDate 1 as
where
fireworkDate k aas@(a : as) = a - k : fireworkDate (succ k) (if a == k then as else aas)
fireworkDate _ [] = []
反省としては、TLEになったとき計算量を抑える方法を考えることかな、ということです。(単純に修行量が足りないだけなのですが)
ちなみに、zipWithを使うともっとシンプルに解けるみたいです。(これはhttps://atcoder.jp/contests/abc322/submissions/46149412に投稿しています。)zipWith便利。
diff :: Num c => [c] -> [c]
diff lst = zipWith (-) lst (0 : init lst)
main :: IO ()
main = do
_ <- BS.getLine
as <- unfoldr (BS.readInt . BS.dropWhile isSpace) <$> BS.getLine
let diffDates = map (+ (-1)) $ diff as
let ans = diffDates >>= \date -> reverse [0 .. date]
mapM_ print ans