2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AtCoder482振り返り

2
Posted at

AtCoder482振り返りです。

結果

AB完でした。

スクリーンショット 2026-11-01 13.27.46.png

スクリーンショット 2026-11-01 13.28.05.png

ふりかえり

A問題

問題文通り解くだけです

main :: IO ()
main = do
  s <- getLine
  putStrLn $ bool "odd" "even" $ even (length [() | c <- s, c == 'o'])

B問題

行、列、斜めで全探索しました。
もっと綺麗に書けたかもしれませんが、愚直に解いています。

main :: IO ()
main = do
  ss <- replicateM 5 getLine
  let grid = IA.listArray @UArray ((1, 1), (5, 5)) $ concat ss
      r = maximum [cnts | i <- [1 .. 5], let cnts = length [() | j <- [1 .. 5], grid IA.! (i, j) == 'o']]
      c = maximum [cnts | j <- [1 .. 5], let cnts = length [() | i <- [1 .. 5], grid IA.! (i, j) == 'o']]
      d1 = length [() | i <- [1 .. 5], j <- [1 .. 5], i == j, grid IA.! (i, j) == 'o']
      d2 = length [() | i <- [1 .. 5], j <- [1 .. 5], i + j == 6, grid IA.! (i, j) == 'o']
  print $ 5 - maximum [r, c, d1, d2]

C問題(upsolved)

区間の個数を求めることから、累積和で解けそう。と思いきや

1≤H,W≤10^9, 1≤u≤d≤H, 1≤l≤r≤W
の制約があるのでメモリ不足でREになります。

solve :: [(Int, Int)] -> (Int, Int) -> [[Int]] -> [Int]
solve rcs (h, w) =
  map
    ( \q -> case q of
        [1, u, d] -> rcsums VU.! d - rcsums VU.! (u - 1)
        [2, l, r] -> ccsums VU.! r - ccsums VU.! (l - 1)
        _ -> error "invalid query"
    )
  where
    (rs, cs) = unzip rcs
    rsums = elems $ accumArray @UArray (+) 0 (1, h) $ map (,1) rs
    csums = elems $ accumArray @UArray (+) 0 (1, w) $ map (,1) cs
    rcsums = VU.fromList $ scanl' (+) 0 rsums
    ccsums = VU.fromList $ scanl' (+) 0 csums

-- Main
main :: IO ()
main = do
  [h, w, n, q] <- getInts
  rcs <- replicateM n getPairInt
  qs <- replicateM q getInts
  mapM_ print $ solve rcs (h, w) qs

UArrayのIntは一つの要素ごとに8byteを使うので、一つのarrayで8 * 10^9 ≒ 8GBのメモリを使うことになります。
AtCoderは通常1024MiBであることから、(1, w)もしくは(1, h)のarrayを作るとメモリが足りずエラーとなります。

参考までに、型ごとのメモリの目安をまとめておきます。

配列の種類 1要素あたり 実用的な上限の目安(要素数)
UArray / IOUArray / STUArray の Int 8 byte 約 5×10⁷〜10⁸(10⁸で約800MB、ギリギリ)
同上の Int32 4 byte 約 2×10⁸
同上の Word8 1 byte 約 8×10⁸
同上の Bool 1 bit(ビット詰め) 10⁹ でも約125MB
boxed Array(Array Int Int など) ポインタ8byte+ボックス化した値(Intなら16byte)+サンク 約 10⁷ 程度

メモリ領域が足りず累積和を使えない場合、どうすればいいのでしょう
この場合は、二分探索を使うとよさそうです。

あらかじめ駒の位置でsortしておき、区間の最小値、最大値を二分探索で解きます。これなら新しくarrayを作る必要がないのでメモリを大幅に使わず区間の大きさを求めることができます。

 solve :: [(Int, Int)] -> (Int, Int) -> [[Int]] -> [Int]
solve rcs (h, w) =
  map
    ( \q -> case q of
        [1, u, d] -> (maybe (VU.length rs' - 1) pred (lookupGTIdxV d rs')) - (maybe 0 succ (lookupLTIdxV u rs')) + 1
        [2, l, r] -> (maybe (VU.length cs' - 1) pred (lookupGTIdxV r cs')) - (maybe 0 succ (lookupLTIdxV l cs')) + 1
    )
  where
    (rs, cs) = unzip rcs
    rs' = VU.fromList $ sort rs
    cs' = VU.fromList $ sort cs

-- Main
main :: IO ()
main = do
  [h, w, n, q] <- getInts
  rcs <- replicateM n getPairInt
  qs <- replicateM q getInts
  mapM_ print $ solve rcs (h, w) qs

全体を振り返って

以下反省点です

  1. 空間計算量の見積もりを怠った(というより許容範囲を把握していなかった) -> AtCoderの使用可能なメモリ量を把握しておく
  2. REが出たときにエラーの原因を突き止めるのに時間がかかった -> 1ができればエラーの原因に検討がつくのでなんとかできるはず
  3. 二分探索で区間の大きさを求める手法をしらなかった -> 今回の問題を復習してとけるようにしておく

引き続き頑張ります!

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?