# ABC315 振り返り
- [キーエンスプログラミングコンテスト2023夏(AtCoder Beginner Contest 315) - AtCoder](https://atcoder.jp/contests/abc315)
- 成績 ABC 3完 (763) ··· [コンテスト成績証 - AtCoder](https://atcoder.jp/users/oceajigger/history/share/abc315)
- 前回 [[ABC314 振り返り]]
うーん、とても悔しい回でした。
ABC までは比較的調子よく解いていたのですが、D の問題文を誤読してつまづきました。
結局 D は飛ばして E に行ったのですが、ここでも方針はあってたのですがミスを二つ重ねてしまい、ゲームオーバー。
D は仕方がないとして E は今の自分の実力で十分に解ける問題だったので、悔いが残ります。本戦終わって「悔しい」と思うのは初めてかもしれないです。全然解けなかったとかなら悔しいとは思わないですが、解けると思ったものが解けなかったのは、悔しいですね 😣
入緑にリーチ気味なので、E を解いて...と行きたかったのですが、次回以降におあずけです。
----
## [A - tcdr](https://atcoder.jp/contests/abc315/tasks/abc315_a)
- [提出 #44771360 - キーエンスプログラミングコンテスト2023夏(AtCoder Beginner Contest 315)](https://atcoder.jp/contests/abc315/submissions/44771360)
特に引っ掛けっぽいところもなく。素直に実装。
```haskell
main :: IO ()
main = do
s <- getLine
let xs = Set.fromList ['a', 'e', 'i', 'o', 'u']
s' = filter (`Set.notMember` xs) s
putStrLn s'
```
----
## [B - The Middle Day](https://atcoder.jp/contests/abc315/tasks/abc315_b)
- [提出 #44771326 - キーエンスプログラミングコンテスト2023夏(AtCoder Beginner Contest 315)](https://atcoder.jp/contests/abc315/submissions/44771326)
どうやろうかなと少し考えましたが、計算量が少ないので `31` を `1, 2, 3, 4 ... 31` と展開して、全探索しました。
足し算引き算で計算していくことも考えましたが、多分それやるとはまります。
```haskell
main :: IO ()
main = do
_ <- getInt
ds <- getInts
let x = sum ds `div` 2
(month, day) = head . drop x $ concatMap (\(m, d) -> map (m,) [1 .. d]) $ zip [1 ..] ds
putStrLn . unwords . map show $ [month, day]
```
----
## [C - Flavors](https://atcoder.jp/contests/abc315/tasks/abc315_c)
- [提出 #44771343 - キーエンスプログラミングコンテスト2023夏(AtCoder Beginner Contest 315)](https://atcoder.jp/contests/abc315/submissions/44771343)
(1) 全体をソートして top 2 を計算 ··· これが異なる味のベスト
(2) 同じ味のものでまとめ上げて、それぞれの味の top 2 を計算。うち、最大のものが同じ味のベスト
1 と 2 の max をとったものが答え。
top 2 をとったつもりが 1 個しか無かったとかその辺の罠がありそうで慎重を期して一応その辺はガードしましたが、必要だったかどうかよくわかってないです。
```haskell
solve case1 case2
| length case1 < 2 = maximum case2
| null case2 = sum case1
| otherwise = max (sum case1) (maximum case2)
main :: IO ()
main = do
n <- getInt
uvs <- replicateM n getTuple
let (k, _) = maximumOn fst uvs
g = graph (1, k) uvs
let case1 = take 2 . sortOn Down . map maximum $ filter (not . null) (elems g)
case2 = map (\[s, t] -> s + (t `div` 2)) $ filter (\xs -> length xs == 2) $ map (take 2 . sortOn Down) (elems g)
print $ solve case1 case2
```
----
## [D - Magical Cookies](https://atcoder.jp/contests/abc315/tasks/abc315_d) (🍊 未完)
問題文を誤読してしまいました。
> その行に $2$ 枚以上のクッキーが残っており、それらの色がすべて同じならば、それらに印をつける。
これを「ある行に同じ色のクッキーが2枚以上あったら、そこにある同じ色のものは印がつく」と解釈してしまいました。この解釈だとただ実装が面倒なだけで、とても簡単です。勘違いしたことで「なんでこんな問題が D で出るんだ? 何かがおかしくないか...」と結構悩みましたが、これを余計な悩みと言わずなんというかw
よくわからないけど簡単な問題なんだろうかと思って実装して送信したところ WA。ええー、っていう。
実装が面倒なこともあり、30分ほど無駄にしてしまいました。
質問もあったようだし、同じところで疑問に思った人が結構いたのではないかと想像します。
順位表を見てみたところ、自分の周囲の人もほとんど解けてなかったので飛ばすことにしました。
----
## [E - Prerequisites](https://atcoder.jp/contests/abc315/tasks/abc315_e) (コンテスト後にAC)
- [提出 #44770617 - キーエンスプログラミングコンテスト2023夏(AtCoder Beginner Contest 315)](https://atcoder.jp/contests/abc315/submissions/44770617)
これをコンテスト中に AC できなかったのは、悔しいです。
ミスを二つほどしてしまい WA を重ねて時間切れになってしまいました。
正しい方針は
1. $1$ から各頂点へ向かう有向グラフを作って DFS か BFS で、$1$ から辿れる頂点集合に絞り込む。
2. 各頂点から $1$ の方向へ向かう有向グラフを作って、1 で見つけた集合に対してトポロジカルソート
となるのですが、
- 1 に Union-Find を使ってしまうというミスをしました。Union-Find だと 1 に向かってない頂点まで連結で集めてしまいます。WA が何回か出て、それに気づきました。
- 2 自分で実装したトポロジカルソートライブラリの動きを、間違えて捉えてました。実装が間違っていたというより、動きで誤解している部分があった。このせいで 1 の集合が合っていても WA になってしまう
というミスを重ねてしまいました。ぬう
```haskell
main :: IO ()
main = do
n <- readLn @Int
xs <- replicateM n $ do
(_ : ps) <- getInts
return ps
-- 1 から各頂点へ向かうグラフ
let uvs = concatMap (\(i, ps) -> map (i,) ps) $ zip [1 ..] xs
g = graph (1, n) uvs
dist = bfs (g !) (-1) (1, n) [1]
vs = map fst $ filterOnSnd (/= -1) $ assocs dist
-- 各頂点から1へ向かうグラフ
let uvs' = concatMap (\(i, ps) -> map (,i) ps) $ zip [1 ..] xs
g2 = graph (1, n) uvs'
let !_ = dbg ("g", g)
let !_ = dbg ("g2", g2)
vs' <- topSortM (g2 !) (bounds g2) vs
putStrLn . unwords . map show $ init vs'
```
----
## 感想・反省など
悔しい回でしたが、悔しいと思えるのは良いことだと思います。
自分の実力が上がってきているからこそ、解けるはずの問題が解けないという悔しさを感じるようになったんでしょうし、記憶に強く残るので同じミスはもう起こさないことでしょう。悔しさをバネに、もっと精進しなければという気持ちにもなります。
競技プログラミングはやればやるほど、こういう悔しさですとか、自分自身への不甲斐なさのような感情をその後の成長材料に転換できるかを試される世界だなあと思います。引き続き頑張ります。
ところで、今日は夕方に有酸素運動をする時間がなかったです。
そのせいか、ここ最近に比較しまた緊張がぶり返した感がありました。やっぱり私の場合は運動するなり熱い風呂に入るなりして、精神的にリラックスしてから臨むと良いようです。それがわかったのは収穫です。
## WJ で待たされる問題
新ジャッジになってから、Haskell のコードをサーバーに送信したあとしばらく「WJ」状態で待たされるようになりました。体感では1分ぐらいかかっているような気が...
これがちょっと問題でして、自分が送信した回答が AC したかどうかがすぐに確認できません。
AC してるかわからないまま次の問題文を読むのですが、やはり結果が気になって問題文が頭に入ってきません。
トータルで、結構な時間とメンタルHPをこれでロスしている感じがあります。いつか改善されることを祈ります。