ABC 417
ABC 417 に参加しました。
A 問題
文字列 の先頭 文字、末尾 文字を削除せよ。 dropEnd 関数を知っていると楽できますね。
solve :: StateT BS.ByteString IO ()
solve = do
(!n, !a, !b) <- ints3'
!s <- line'
printBSB . BS.dropEnd b $ BS.drop a sB 問題
数列 から数列 の要素を 1 つずつ削除せよ。 (\\\\) 一発で解ける模様です:
solve :: StateT BS.ByteString IO ()
solve = do
(!n, !m) <- ints2'
!xs <- U.toList <$> intsU'
!ys <- U.toList <$> intsU'
printBSB . unwordsBSB . U.fromList $ xs \\ ysC 問題
数列 に対し条件 を満たす の数を求めよ。
本番で考えた方法
下の図で かつ のとき、 に対しては である場合に条件を満たします:
o----o----o----o----o
A_1 A_2 A_3 A_4 A_5
-1 0 1 2ここで頻度列 () を持って、読み出し位置のオフセット () をズラして行くと、 に対して条件を満たす の数が で求められます:
[- 1 - - -]
|0 1 2 j = 1
|0 1 2 3 j = 2
|0 1 2 3 4 j = 3という形で頑張りました。伝わらないかも……
シンプルな解放
の形に変数分離 () すると、各項の値が独立するため簡単になります。 の範囲で走査して で解けます。頭がいいですね:
solve :: StateT BS.ByteString IO ()
solve = do
!n <- int'
!xs <- intsU'
let lhs, rhs :: Int -> Int -> Int
lhs i xi = i + xi
rhs j xj = j - xj
let !res = runST $ do
freq <- UM.replicate (1 + n + 2 * 10 ^ 5) (0 :: Int)
U.ifoldM'
( \acc j xj -> do
dn <- fromMaybe 0 <$> (GM.readMaybe freq $! rhs j xj)
GM.modify freq (+ 1) $! lhs j xj
pure $! acc + dn
)
(0 :: Int)
xs
printBSB resD 問題
個の関数を連結するとき、様々な入力に対する出力を求めよ。それぞれの関数 は の範囲で以下の通り定義する:
の間は、常に が選択されることが分かります。各点の入出力を の範囲で持つことにすると、 の範囲は二分探索で計算できそうです。
各点で の範囲で入出力表を持つことにして、最後の関数から順に (入力 → 最終出力) を計算していくと解けます。
E 問題
単純無向連結グラフにおいて、 から への辞書順最小パスを で求め、経路復元せよ。
Dijkstra 法において、コストを ByteString 型の経路にすると WA になりました。 Text 型の経路にすると AC しました。 ByteString の比較はバイト列の比較ですから、文字コードが 255 を超えると正しく判定できなくなるようです。